1/*
2 * Copyright (c) 2001-2008 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License").  You may not use this file except in compliance with the
9 * License.  Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22
23/*
24 * ATATimerEventSource.cpp
25 *
26 *	implements a timer event source that can be checked from behind the
27 *  workloop for a timeout event.
28 */
29
30#include <sys/cdefs.h>
31
32__BEGIN_DECLS
33#include <kern/thread_call.h>
34__END_DECLS
35
36#include <IOKit/assert.h>
37#include <IOKit/system.h>
38
39#include <IOKit/IOLib.h>
40#include <IOKit/IOTimerEventSource.h>
41#include <IOKit/IOWorkLoop.h>
42#include "ATATimerEventSource.h"
43
44
45#define super IOTimerEventSource
46OSDefineMetaClassAndStructors(ATATimerEventSource, IOTimerEventSource)
47OSMetaClassDefineReservedUnused(ATATimerEventSource, 0);
48OSMetaClassDefineReservedUnused(ATATimerEventSource, 1);
49OSMetaClassDefineReservedUnused(ATATimerEventSource, 2);
50OSMetaClassDefineReservedUnused(ATATimerEventSource, 3);
51OSMetaClassDefineReservedUnused(ATATimerEventSource, 4);
52OSMetaClassDefineReservedUnused(ATATimerEventSource, 5);
53OSMetaClassDefineReservedUnused(ATATimerEventSource, 6);
54OSMetaClassDefineReservedUnused(ATATimerEventSource, 7);
55
56// the interesting part of the function.
57bool
58ATATimerEventSource::hasTimedOut( void )
59{
60	return (hasExpired == kTimedOutTrue);
61}
62
63
64// Timeout handler function. This function is called by the kernel when
65// the timeout interval expires.
66//
67void ATATimerEventSource::myTimeout(void *self)
68{
69    ATATimerEventSource *me = (ATATimerEventSource *) self;
70
71	OSCompareAndSwap( kTimedOutFalse, kTimedOutTrue, &(me->hasExpired) );
72
73	// pasted from superclass's static handler.
74
75	if (me->enabled)
76	{
77        Action doit = (Action) me->action;
78
79        if (doit)
80		{
81            me->closeGate();
82            (*doit)(me->owner, me);
83            me->openGate();
84        }
85    }
86}
87
88void ATATimerEventSource::setTimeoutFunc()
89{
90    calloutEntry = (void *) thread_call_allocate((thread_call_func_t) myTimeout,
91                                                 (thread_call_param_t) this);
92}
93
94bool ATATimerEventSource::init(OSObject *inOwner, Action inAction)
95{
96    if ( !super::init( (OSObject *)inOwner, (Action) inAction) )
97        return false;
98
99	hasExpired = kTimedOutFalse;
100
101    return true;
102}
103
104
105ATATimerEventSource *
106ATATimerEventSource::ataTimerEventSource(OSObject *inOwner, Action inAction)
107{
108    ATATimerEventSource *me = new ATATimerEventSource;
109
110    if (me && !me->init(inOwner, inAction)) {
111        me->free();
112        return 0;
113    }
114
115    return me;
116}
117void ATATimerEventSource::cancelTimeout()
118{
119	hasExpired = kTimedOutFalse;
120	super::cancelTimeout();
121}
122
123void ATATimerEventSource::enable()
124{
125	hasExpired = kTimedOutFalse;
126    super::enable();
127}
128
129void ATATimerEventSource::disable()
130{
131	hasExpired = kTimedOutFalse;
132
133    super::disable();
134}
135
136IOReturn ATATimerEventSource::wakeAtTime(UnsignedWide inAbstime)
137{
138	hasExpired = kTimedOutFalse;
139#if ABSOLUTETIME_SCALAR_TYPE
140	UInt64	abstime = (UInt64)inAbstime.hi << 32 | (UInt64)inAbstime.lo;
141    return super::wakeAtTime( abstime );
142#else
143	return super::wakeAtTime(inAbstime);
144#endif	/* ABSOLUTETIME_SCALAR_TYPE */
145}
146