1c1dac77fSApple OSS Distributions /*
2*a3bb9fccSApple OSS Distributions  * Copyright (c) 1998-2014 Apple Inc. All rights reserved.
3c1dac77fSApple OSS Distributions  *
4e13b1fa5SApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5c1dac77fSApple OSS Distributions  *
6e13b1fa5SApple OSS Distributions  * This file contains Original Code and/or Modifications of Original Code
7e13b1fa5SApple OSS Distributions  * as defined in and that are subject to the Apple Public Source License
8e13b1fa5SApple OSS Distributions  * Version 2.0 (the 'License'). You may not use this file except in
9e13b1fa5SApple OSS Distributions  * compliance with the License. The rights granted to you under the License
10e13b1fa5SApple OSS Distributions  * may not be used to create, or enable the creation or redistribution of,
11e13b1fa5SApple OSS Distributions  * unlawful or unlicensed copies of an Apple operating system, or to
12e13b1fa5SApple OSS Distributions  * circumvent, violate, or enable the circumvention or violation of, any
13e13b1fa5SApple OSS Distributions  * terms of an Apple operating system software license agreement.
14c1dac77fSApple OSS Distributions  *
15e13b1fa5SApple OSS Distributions  * Please obtain a copy of the License at
16e13b1fa5SApple OSS Distributions  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17e13b1fa5SApple OSS Distributions  *
18e13b1fa5SApple OSS Distributions  * The Original Code and all software distributed under the License are
19e13b1fa5SApple OSS Distributions  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20c1dac77fSApple OSS Distributions  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21c1dac77fSApple OSS Distributions  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22e13b1fa5SApple OSS Distributions  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23e13b1fa5SApple OSS Distributions  * Please see the License for the specific language governing rights and
24e13b1fa5SApple OSS Distributions  * limitations under the License.
25c1dac77fSApple OSS Distributions  *
26e13b1fa5SApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27c1dac77fSApple OSS Distributions  */
28c1dac77fSApple OSS Distributions 
29c1dac77fSApple OSS Distributions #include <IOKit/IOInterruptEventSource.h>
30855239e5SApple OSS Distributions #include <IOKit/IOKitDebug.h>
31c1dac77fSApple OSS Distributions #include <IOKit/IOLib.h>
32c1dac77fSApple OSS Distributions #include <IOKit/IOService.h>
33c1dac77fSApple OSS Distributions #include <IOKit/IOInterrupts.h>
34c1dac77fSApple OSS Distributions #include <IOKit/IOTimeStamp.h>
35c1dac77fSApple OSS Distributions #include <IOKit/IOWorkLoop.h>
36*a3bb9fccSApple OSS Distributions #include <IOKit/IOInterruptAccountingPrivate.h>
37c1dac77fSApple OSS Distributions 
38855239e5SApple OSS Distributions #if IOKITSTATS
39c1dac77fSApple OSS Distributions 
40855239e5SApple OSS Distributions #define IOStatisticsInitializeCounter() \
41c1dac77fSApple OSS Distributions do { \
42855239e5SApple OSS Distributions 	IOStatistics::setCounterType(IOEventSource::reserved->counter, kIOStatisticsInterruptEventSourceCounter); \
43c1dac77fSApple OSS Distributions } while (0)
44c1dac77fSApple OSS Distributions 
45855239e5SApple OSS Distributions #define IOStatisticsCheckForWork() \
46c1dac77fSApple OSS Distributions do { \
47855239e5SApple OSS Distributions 	IOStatistics::countInterruptCheckForWork(IOEventSource::reserved->counter); \
48c1dac77fSApple OSS Distributions } while (0)
49c1dac77fSApple OSS Distributions 
50855239e5SApple OSS Distributions #define IOStatisticsInterrupt() \
51c1dac77fSApple OSS Distributions do { \
52855239e5SApple OSS Distributions 	IOStatistics::countInterrupt(IOEventSource::reserved->counter); \
53c1dac77fSApple OSS Distributions } while (0)
54c1dac77fSApple OSS Distributions 
55855239e5SApple OSS Distributions #else
56855239e5SApple OSS Distributions 
57855239e5SApple OSS Distributions #define IOStatisticsInitializeCounter()
58855239e5SApple OSS Distributions #define IOStatisticsCheckForWork()
59855239e5SApple OSS Distributions #define IOStatisticsInterrupt()
60855239e5SApple OSS Distributions 
61855239e5SApple OSS Distributions #endif // IOKITSTATS
62c1dac77fSApple OSS Distributions 
63c1dac77fSApple OSS Distributions #define super IOEventSource
64c1dac77fSApple OSS Distributions 
65c1dac77fSApple OSS Distributions OSDefineMetaClassAndStructors(IOInterruptEventSource, IOEventSource)
66c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOInterruptEventSource, 0);
67c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOInterruptEventSource, 1);
68c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOInterruptEventSource, 2);
69c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOInterruptEventSource, 3);
70c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOInterruptEventSource, 4);
71c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOInterruptEventSource, 5);
72c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOInterruptEventSource, 6);
73c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOInterruptEventSource, 7);
74c1dac77fSApple OSS Distributions 
75c1dac77fSApple OSS Distributions bool IOInterruptEventSource::init(OSObject *inOwner,
76368ad365SApple OSS Distributions 				  Action inAction,
77368ad365SApple OSS Distributions 				  IOService *inProvider,
78368ad365SApple OSS Distributions 				  int inIntIndex)
79c1dac77fSApple OSS Distributions {
80c1dac77fSApple OSS Distributions     bool res = true;
81c1dac77fSApple OSS Distributions 
82c1dac77fSApple OSS Distributions     if ( !super::init(inOwner, (IOEventSourceAction) inAction) )
83c1dac77fSApple OSS Distributions         return false;
84c1dac77fSApple OSS Distributions 
85*a3bb9fccSApple OSS Distributions     reserved = IONew(ExpansionData, 1);
86*a3bb9fccSApple OSS Distributions 
87*a3bb9fccSApple OSS Distributions     if (!reserved) {
88*a3bb9fccSApple OSS Distributions         return false;
89*a3bb9fccSApple OSS Distributions     }
90*a3bb9fccSApple OSS Distributions 
91*a3bb9fccSApple OSS Distributions     bzero(reserved, sizeof(ExpansionData));
92*a3bb9fccSApple OSS Distributions 
93c1dac77fSApple OSS Distributions     provider = inProvider;
94c1dac77fSApple OSS Distributions     producerCount = consumerCount = 0;
95c1dac77fSApple OSS Distributions     autoDisable = explicitDisable = false;
96855239e5SApple OSS Distributions     intIndex = ~inIntIndex;
97c1dac77fSApple OSS Distributions 
98c1dac77fSApple OSS Distributions     // Assumes inOwner holds a reference(retain) on the provider
99c1dac77fSApple OSS Distributions     if (inProvider) {
100*a3bb9fccSApple OSS Distributions         if (IA_ANY_STATISTICS_ENABLED) {
101*a3bb9fccSApple OSS Distributions             /*
102*a3bb9fccSApple OSS Distributions              * We only treat this as an "interrupt" if it has a provider; if it does,
103*a3bb9fccSApple OSS Distributions              * set up the objects necessary to track interrupt statistics.  Interrupt
104*a3bb9fccSApple OSS Distributions              * event sources without providers are most likely being used as simple
105*a3bb9fccSApple OSS Distributions              * event source in order to poke at workloops and kick off work.
106*a3bb9fccSApple OSS Distributions              *
107*a3bb9fccSApple OSS Distributions              * We also avoid try to avoid interrupt accounting overhead if none of
108*a3bb9fccSApple OSS Distributions              * the statistics are enabled.
109*a3bb9fccSApple OSS Distributions              */
110*a3bb9fccSApple OSS Distributions             reserved->statistics = IONew(IOInterruptAccountingData, 1);
111*a3bb9fccSApple OSS Distributions 
112*a3bb9fccSApple OSS Distributions             if (!reserved->statistics) {
113*a3bb9fccSApple OSS Distributions                 /*
114*a3bb9fccSApple OSS Distributions                  * We rely on the free() routine to clean up after us if init fails
115*a3bb9fccSApple OSS Distributions                  * midway.
116*a3bb9fccSApple OSS Distributions                  */
117*a3bb9fccSApple OSS Distributions                 return false;
118*a3bb9fccSApple OSS Distributions             }
119*a3bb9fccSApple OSS Distributions 
120*a3bb9fccSApple OSS Distributions             bzero(reserved->statistics, sizeof(IOInterruptAccountingData));
121*a3bb9fccSApple OSS Distributions 
122*a3bb9fccSApple OSS Distributions             reserved->statistics->owner = this;
123*a3bb9fccSApple OSS Distributions         }
124*a3bb9fccSApple OSS Distributions 
125855239e5SApple OSS Distributions         res = (kIOReturnSuccess == registerInterruptHandler(inProvider, inIntIndex));
126*a3bb9fccSApple OSS Distributions 
127*a3bb9fccSApple OSS Distributions 	if (res) {
128855239e5SApple OSS Distributions 	    intIndex = inIntIndex;
129855239e5SApple OSS Distributions         }
130*a3bb9fccSApple OSS Distributions     }
131c1dac77fSApple OSS Distributions 
132855239e5SApple OSS Distributions     IOStatisticsInitializeCounter();
133855239e5SApple OSS Distributions 
134855239e5SApple OSS Distributions     return res;
135855239e5SApple OSS Distributions }
136855239e5SApple OSS Distributions 
137855239e5SApple OSS Distributions IOReturn IOInterruptEventSource::registerInterruptHandler(IOService *inProvider,
138855239e5SApple OSS Distributions 				  int inIntIndex)
139855239e5SApple OSS Distributions {
140855239e5SApple OSS Distributions     IOReturn ret;
141855239e5SApple OSS Distributions     int intType;
142c1dac77fSApple OSS Distributions     IOInterruptAction intHandler;
143c1dac77fSApple OSS Distributions 
144855239e5SApple OSS Distributions     ret = inProvider->getInterruptType(inIntIndex, &intType);
145855239e5SApple OSS Distributions     if (kIOReturnSuccess != ret)
146855239e5SApple OSS Distributions 	return (ret);
147855239e5SApple OSS Distributions 
148c1dac77fSApple OSS Distributions     autoDisable = (intType == kIOInterruptTypeLevel);
149c1dac77fSApple OSS Distributions     if (autoDisable) {
15014e3d835SApple OSS Distributions 	intHandler = OSMemberFunctionCast(IOInterruptAction,
15114e3d835SApple OSS Distributions 	    this, &IOInterruptEventSource::disableInterruptOccurred);
152c1dac77fSApple OSS Distributions     }
153c1dac77fSApple OSS Distributions     else
15414e3d835SApple OSS Distributions 	intHandler = OSMemberFunctionCast(IOInterruptAction,
15514e3d835SApple OSS Distributions 	    this, &IOInterruptEventSource::normalInterruptOccurred);
156c1dac77fSApple OSS Distributions 
157855239e5SApple OSS Distributions     ret = provider->registerInterrupt(inIntIndex, this, intHandler);
158c1dac77fSApple OSS Distributions 
159*a3bb9fccSApple OSS Distributions     /*
160*a3bb9fccSApple OSS Distributions      * Add statistics to the provider.  The setWorkLoop convention should ensure
161*a3bb9fccSApple OSS Distributions      * that we always go down the unregister path before we register (outside of
162*a3bb9fccSApple OSS Distributions      * init()), so we don't have to worry that we will invoke addInterruptStatistics
163*a3bb9fccSApple OSS Distributions      * erroneously.
164*a3bb9fccSApple OSS Distributions      */
165*a3bb9fccSApple OSS Distributions     if ((ret == kIOReturnSuccess) && (reserved->statistics)) {
166*a3bb9fccSApple OSS Distributions         /*
167*a3bb9fccSApple OSS Distributions          * Stash the normal index value, for the sake of debugging.
168*a3bb9fccSApple OSS Distributions          */
169*a3bb9fccSApple OSS Distributions         reserved->statistics->interruptIndex = inIntIndex;
170*a3bb9fccSApple OSS Distributions 
171*a3bb9fccSApple OSS Distributions         /*
172*a3bb9fccSApple OSS Distributions          * We need to hook the interrupt information up to the provider so that it
173*a3bb9fccSApple OSS Distributions          * can find the statistics for this interrupt when desired.  The provider is
174*a3bb9fccSApple OSS Distributions          * responsible for maintaining the reporter for a particular interrupt, and
175*a3bb9fccSApple OSS Distributions          * needs a handle on the statistics so that it can request that the reporter
176*a3bb9fccSApple OSS Distributions          * be updated as needed.  Errors are considered "soft" for the moment (it
177*a3bb9fccSApple OSS Distributions          * will either panic, or fail in a way such that we can still service the
178*a3bb9fccSApple OSS Distributions          * interrupt).
179*a3bb9fccSApple OSS Distributions          */
180*a3bb9fccSApple OSS Distributions         provider->addInterruptStatistics(reserved->statistics, inIntIndex);
181*a3bb9fccSApple OSS Distributions 
182*a3bb9fccSApple OSS Distributions         /*
183*a3bb9fccSApple OSS Distributions          * Add the statistics object to the global list of statistics objects; this
184*a3bb9fccSApple OSS Distributions          * is an aid to debugging (we can trivially find statistics for all eligible
185*a3bb9fccSApple OSS Distributions          * interrupts, and dump them; potentially helpful if the system is wedged
186*a3bb9fccSApple OSS Distributions          * due to interrupt activity).
187*a3bb9fccSApple OSS Distributions          */
188*a3bb9fccSApple OSS Distributions         interruptAccountingDataAddToList(reserved->statistics);
189*a3bb9fccSApple OSS Distributions     }
190*a3bb9fccSApple OSS Distributions 
191855239e5SApple OSS Distributions     return (ret);
192c1dac77fSApple OSS Distributions }
193c1dac77fSApple OSS Distributions 
194*a3bb9fccSApple OSS Distributions void
195*a3bb9fccSApple OSS Distributions IOInterruptEventSource::unregisterInterruptHandler(IOService *inProvider,
196*a3bb9fccSApple OSS Distributions 				  int inIntIndex)
197*a3bb9fccSApple OSS Distributions {
198*a3bb9fccSApple OSS Distributions     if (reserved->statistics) {
199*a3bb9fccSApple OSS Distributions         interruptAccountingDataRemoveFromList(reserved->statistics);
200*a3bb9fccSApple OSS Distributions         provider->removeInterruptStatistics(reserved->statistics->interruptIndex);
201*a3bb9fccSApple OSS Distributions     }
202*a3bb9fccSApple OSS Distributions 
203*a3bb9fccSApple OSS Distributions     provider->unregisterInterrupt(inIntIndex);
204*a3bb9fccSApple OSS Distributions }
205*a3bb9fccSApple OSS Distributions 
206*a3bb9fccSApple OSS Distributions 
207c1dac77fSApple OSS Distributions IOInterruptEventSource *
208c1dac77fSApple OSS Distributions IOInterruptEventSource::interruptEventSource(OSObject *inOwner,
209c1dac77fSApple OSS Distributions 					     Action inAction,
210c1dac77fSApple OSS Distributions 					     IOService *inProvider,
211c1dac77fSApple OSS Distributions 					     int inIntIndex)
212c1dac77fSApple OSS Distributions {
213c1dac77fSApple OSS Distributions     IOInterruptEventSource *me = new IOInterruptEventSource;
214c1dac77fSApple OSS Distributions 
215c1dac77fSApple OSS Distributions     if (me && !me->init(inOwner, inAction, inProvider, inIntIndex)) {
216368ad365SApple OSS Distributions         me->release();
217c1dac77fSApple OSS Distributions         return 0;
218c1dac77fSApple OSS Distributions     }
219c1dac77fSApple OSS Distributions 
220c1dac77fSApple OSS Distributions     return me;
221c1dac77fSApple OSS Distributions }
222c1dac77fSApple OSS Distributions 
223c1dac77fSApple OSS Distributions void IOInterruptEventSource::free()
224c1dac77fSApple OSS Distributions {
225855239e5SApple OSS Distributions     if (provider && intIndex >= 0)
226*a3bb9fccSApple OSS Distributions         unregisterInterruptHandler(provider, intIndex);
227*a3bb9fccSApple OSS Distributions 
228*a3bb9fccSApple OSS Distributions     if (reserved) {
229*a3bb9fccSApple OSS Distributions         if (reserved->statistics) {
230*a3bb9fccSApple OSS Distributions             IODelete(reserved->statistics, IOInterruptAccountingData, 1);
231*a3bb9fccSApple OSS Distributions         }
232*a3bb9fccSApple OSS Distributions 
233*a3bb9fccSApple OSS Distributions         IODelete(reserved, ExpansionData, 1);
234*a3bb9fccSApple OSS Distributions     }
235c1dac77fSApple OSS Distributions 
236c1dac77fSApple OSS Distributions     super::free();
237c1dac77fSApple OSS Distributions }
238c1dac77fSApple OSS Distributions 
239c1dac77fSApple OSS Distributions void IOInterruptEventSource::enable()
240c1dac77fSApple OSS Distributions {
241855239e5SApple OSS Distributions     if (provider && intIndex >= 0) {
242c1dac77fSApple OSS Distributions         provider->enableInterrupt(intIndex);
243c1dac77fSApple OSS Distributions         explicitDisable = false;
244e13b1fa5SApple OSS Distributions         enabled = true;
245c1dac77fSApple OSS Distributions     }
246c1dac77fSApple OSS Distributions }
247c1dac77fSApple OSS Distributions 
248c1dac77fSApple OSS Distributions void IOInterruptEventSource::disable()
249c1dac77fSApple OSS Distributions {
250855239e5SApple OSS Distributions     if (provider && intIndex >= 0) {
251c1dac77fSApple OSS Distributions         provider->disableInterrupt(intIndex);
252c1dac77fSApple OSS Distributions         explicitDisable = true;
253e13b1fa5SApple OSS Distributions         enabled = false;
254c1dac77fSApple OSS Distributions     }
255c1dac77fSApple OSS Distributions }
256c1dac77fSApple OSS Distributions 
257855239e5SApple OSS Distributions void IOInterruptEventSource::setWorkLoop(IOWorkLoop *inWorkLoop)
258855239e5SApple OSS Distributions {
259186b8fceSApple OSS Distributions     if (inWorkLoop) super::setWorkLoop(inWorkLoop);
260855239e5SApple OSS Distributions 
261186b8fceSApple OSS Distributions     if (provider) {
262855239e5SApple OSS Distributions 	if (!inWorkLoop) {
263855239e5SApple OSS Distributions 	    if (intIndex >= 0) {
264*a3bb9fccSApple OSS Distributions                 /*
265*a3bb9fccSApple OSS Distributions                  * It isn't necessarily safe to wait until free() to unregister the interrupt;
266*a3bb9fccSApple OSS Distributions                  * our provider may disappear.
267*a3bb9fccSApple OSS Distributions                  */
268*a3bb9fccSApple OSS Distributions                 unregisterInterruptHandler(provider, intIndex);
269855239e5SApple OSS Distributions 		intIndex = ~intIndex;
270855239e5SApple OSS Distributions 	    }
271855239e5SApple OSS Distributions 	} else if ((intIndex < 0) && (kIOReturnSuccess == registerInterruptHandler(provider, ~intIndex))) {
272855239e5SApple OSS Distributions 	    intIndex = ~intIndex;
273855239e5SApple OSS Distributions 	}
274855239e5SApple OSS Distributions     }
275855239e5SApple OSS Distributions 
276186b8fceSApple OSS Distributions     if (!inWorkLoop) super::setWorkLoop(inWorkLoop);
277186b8fceSApple OSS Distributions }
278186b8fceSApple OSS Distributions 
279c1dac77fSApple OSS Distributions const IOService *IOInterruptEventSource::getProvider() const
280c1dac77fSApple OSS Distributions {
281c1dac77fSApple OSS Distributions     return provider;
282c1dac77fSApple OSS Distributions }
283c1dac77fSApple OSS Distributions 
284c1dac77fSApple OSS Distributions int IOInterruptEventSource::getIntIndex() const
285c1dac77fSApple OSS Distributions {
286c1dac77fSApple OSS Distributions     return intIndex;
287c1dac77fSApple OSS Distributions }
288c1dac77fSApple OSS Distributions 
289c1dac77fSApple OSS Distributions bool IOInterruptEventSource::getAutoDisable() const
290c1dac77fSApple OSS Distributions {
291c1dac77fSApple OSS Distributions     return autoDisable;
292c1dac77fSApple OSS Distributions }
293c1dac77fSApple OSS Distributions 
294c1dac77fSApple OSS Distributions bool IOInterruptEventSource::checkForWork()
295c1dac77fSApple OSS Distributions {
296*a3bb9fccSApple OSS Distributions     uint64_t startSystemTime = 0;
297*a3bb9fccSApple OSS Distributions     uint64_t endSystemTime = 0;
298*a3bb9fccSApple OSS Distributions     uint64_t startCPUTime = 0;
299*a3bb9fccSApple OSS Distributions     uint64_t endCPUTime = 0;
300c1dac77fSApple OSS Distributions     unsigned int cacheProdCount = producerCount;
301c1dac77fSApple OSS Distributions     int numInts = cacheProdCount - consumerCount;
302c1dac77fSApple OSS Distributions     IOInterruptEventAction intAction = (IOInterruptEventAction) action;
303855239e5SApple OSS Distributions 	bool trace = (gIOKitTrace & kIOTraceIntEventSource) ? true : false;
304c1dac77fSApple OSS Distributions 
305855239e5SApple OSS Distributions     IOStatisticsCheckForWork();
306c1dac77fSApple OSS Distributions 
307855239e5SApple OSS Distributions 	if ( numInts > 0 )
308855239e5SApple OSS Distributions 	{
309855239e5SApple OSS Distributions 		if (trace)
310855239e5SApple OSS Distributions 			IOTimeStampStartConstant(IODBG_INTES(IOINTES_ACTION),
311d0c1fef6SApple OSS Distributions 						 VM_KERNEL_UNSLIDE(intAction), (uintptr_t) owner, (uintptr_t) this, (uintptr_t) workLoop);
312855239e5SApple OSS Distributions 
313*a3bb9fccSApple OSS Distributions 		if (reserved->statistics) {
314*a3bb9fccSApple OSS Distributions 			if (IA_GET_STATISTIC_ENABLED(kInterruptAccountingSecondLevelSystemTimeIndex)) {
315*a3bb9fccSApple OSS Distributions 				startSystemTime = mach_absolute_time();
316*a3bb9fccSApple OSS Distributions 			}
317*a3bb9fccSApple OSS Distributions 
318*a3bb9fccSApple OSS Distributions 			if (IA_GET_STATISTIC_ENABLED(kInterruptAccountingSecondLevelCPUTimeIndex)) {
319*a3bb9fccSApple OSS Distributions 				startCPUTime = thread_get_runtime_self();
320*a3bb9fccSApple OSS Distributions 			}
321*a3bb9fccSApple OSS Distributions 		}
322*a3bb9fccSApple OSS Distributions 
323855239e5SApple OSS Distributions 		// Call the handler
324c1dac77fSApple OSS Distributions 		(*intAction)(owner, this, numInts);
325855239e5SApple OSS Distributions 
326*a3bb9fccSApple OSS Distributions 		if (reserved->statistics) {
327*a3bb9fccSApple OSS Distributions 			if (IA_GET_STATISTIC_ENABLED(kInterruptAccountingSecondLevelCountIndex)) {
328*a3bb9fccSApple OSS Distributions 				IA_ADD_VALUE(&reserved->statistics->interruptStatistics[kInterruptAccountingSecondLevelCountIndex], 1);
329*a3bb9fccSApple OSS Distributions 			}
330*a3bb9fccSApple OSS Distributions 
331*a3bb9fccSApple OSS Distributions 			if (IA_GET_STATISTIC_ENABLED(kInterruptAccountingSecondLevelCPUTimeIndex)) {
332*a3bb9fccSApple OSS Distributions 				endCPUTime = thread_get_runtime_self();
333*a3bb9fccSApple OSS Distributions 				IA_ADD_VALUE(&reserved->statistics->interruptStatistics[kInterruptAccountingSecondLevelCPUTimeIndex], endCPUTime - startCPUTime);
334*a3bb9fccSApple OSS Distributions 			}
335*a3bb9fccSApple OSS Distributions 
336*a3bb9fccSApple OSS Distributions 			if (IA_GET_STATISTIC_ENABLED(kInterruptAccountingSecondLevelSystemTimeIndex)) {
337*a3bb9fccSApple OSS Distributions 				endSystemTime = mach_absolute_time();
338*a3bb9fccSApple OSS Distributions 				IA_ADD_VALUE(&reserved->statistics->interruptStatistics[kInterruptAccountingSecondLevelSystemTimeIndex], endSystemTime - startSystemTime);
339*a3bb9fccSApple OSS Distributions 			}
340*a3bb9fccSApple OSS Distributions 		}
341*a3bb9fccSApple OSS Distributions 
342855239e5SApple OSS Distributions 		if (trace)
343855239e5SApple OSS Distributions 			IOTimeStampEndConstant(IODBG_INTES(IOINTES_ACTION),
344d0c1fef6SApple OSS Distributions 					       VM_KERNEL_UNSLIDE(intAction), (uintptr_t) owner, (uintptr_t) this, (uintptr_t) workLoop);
345c1dac77fSApple OSS Distributions 
346c1dac77fSApple OSS Distributions 		consumerCount = cacheProdCount;
347c1dac77fSApple OSS Distributions 		if (autoDisable && !explicitDisable)
348c1dac77fSApple OSS Distributions 			enable();
349c1dac77fSApple OSS Distributions 	}
350855239e5SApple OSS Distributions 
351855239e5SApple OSS Distributions 	else if ( numInts < 0 )
352855239e5SApple OSS Distributions 	{
353855239e5SApple OSS Distributions 		if (trace)
354855239e5SApple OSS Distributions 			IOTimeStampStartConstant(IODBG_INTES(IOINTES_ACTION),
355d0c1fef6SApple OSS Distributions 						 VM_KERNEL_UNSLIDE(intAction), (uintptr_t) owner, (uintptr_t) this, (uintptr_t) workLoop);
356855239e5SApple OSS Distributions 
357*a3bb9fccSApple OSS Distributions 		if (reserved->statistics) {
358*a3bb9fccSApple OSS Distributions 			if (IA_GET_STATISTIC_ENABLED(kInterruptAccountingSecondLevelSystemTimeIndex)) {
359*a3bb9fccSApple OSS Distributions 				startSystemTime = mach_absolute_time();
360*a3bb9fccSApple OSS Distributions 			}
361*a3bb9fccSApple OSS Distributions 
362*a3bb9fccSApple OSS Distributions 			if (IA_GET_STATISTIC_ENABLED(kInterruptAccountingSecondLevelCPUTimeIndex)) {
363*a3bb9fccSApple OSS Distributions 				startCPUTime = thread_get_runtime_self();
364*a3bb9fccSApple OSS Distributions 			}
365*a3bb9fccSApple OSS Distributions 		}
366*a3bb9fccSApple OSS Distributions 
367855239e5SApple OSS Distributions 		// Call the handler
368c1dac77fSApple OSS Distributions 		(*intAction)(owner, this, -numInts);
369855239e5SApple OSS Distributions 
370*a3bb9fccSApple OSS Distributions 		if (reserved->statistics) {
371*a3bb9fccSApple OSS Distributions 			if (IA_GET_STATISTIC_ENABLED(kInterruptAccountingSecondLevelCountIndex)) {
372*a3bb9fccSApple OSS Distributions 				IA_ADD_VALUE(&reserved->statistics->interruptStatistics[kInterruptAccountingSecondLevelCountIndex], 1);
373*a3bb9fccSApple OSS Distributions 			}
374*a3bb9fccSApple OSS Distributions 
375*a3bb9fccSApple OSS Distributions 			if (IA_GET_STATISTIC_ENABLED(kInterruptAccountingSecondLevelCPUTimeIndex)) {
376*a3bb9fccSApple OSS Distributions 				endCPUTime = thread_get_runtime_self();
377*a3bb9fccSApple OSS Distributions 				IA_ADD_VALUE(&reserved->statistics->interruptStatistics[kInterruptAccountingSecondLevelCPUTimeIndex], endCPUTime - startCPUTime);
378*a3bb9fccSApple OSS Distributions 			}
379*a3bb9fccSApple OSS Distributions 
380*a3bb9fccSApple OSS Distributions 			if (IA_GET_STATISTIC_ENABLED(kInterruptAccountingSecondLevelSystemTimeIndex)) {
381*a3bb9fccSApple OSS Distributions 				endSystemTime = mach_absolute_time();
382*a3bb9fccSApple OSS Distributions 				IA_ADD_VALUE(&reserved->statistics->interruptStatistics[kInterruptAccountingSecondLevelSystemTimeIndex], endSystemTime - startSystemTime);
383*a3bb9fccSApple OSS Distributions 			}
384*a3bb9fccSApple OSS Distributions 		}
385*a3bb9fccSApple OSS Distributions 
386855239e5SApple OSS Distributions 		if (trace)
387855239e5SApple OSS Distributions 			IOTimeStampEndConstant(IODBG_INTES(IOINTES_ACTION),
388d0c1fef6SApple OSS Distributions 					       VM_KERNEL_UNSLIDE(intAction), (uintptr_t) owner, (uintptr_t) this, (uintptr_t) workLoop);
389c1dac77fSApple OSS Distributions 
390c1dac77fSApple OSS Distributions 		consumerCount = cacheProdCount;
391c1dac77fSApple OSS Distributions 		if (autoDisable && !explicitDisable)
392c1dac77fSApple OSS Distributions 			enable();
393c1dac77fSApple OSS Distributions 	}
394c1dac77fSApple OSS Distributions 
395c1dac77fSApple OSS Distributions     return false;
396c1dac77fSApple OSS Distributions }
397c1dac77fSApple OSS Distributions 
398c1dac77fSApple OSS Distributions void IOInterruptEventSource::normalInterruptOccurred
399c1dac77fSApple OSS Distributions     (void */*refcon*/, IOService */*prov*/, int /*source*/)
400c1dac77fSApple OSS Distributions {
401855239e5SApple OSS Distributions 	bool trace = (gIOKitTrace & kIOTraceIntEventSource) ? true : false;
402c1dac77fSApple OSS Distributions 
403855239e5SApple OSS Distributions     IOStatisticsInterrupt();
404c1dac77fSApple OSS Distributions     producerCount++;
405c1dac77fSApple OSS Distributions 
406855239e5SApple OSS Distributions 	if (trace)
407855239e5SApple OSS Distributions 	    IOTimeStampStartConstant(IODBG_INTES(IOINTES_SEMA), (uintptr_t) this, (uintptr_t) owner);
408c1dac77fSApple OSS Distributions 
409*a3bb9fccSApple OSS Distributions     if (reserved->statistics) {
410*a3bb9fccSApple OSS Distributions         if (IA_GET_STATISTIC_ENABLED(kInterruptAccountingFirstLevelCountIndex)) {
411*a3bb9fccSApple OSS Distributions             IA_ADD_VALUE(&reserved->statistics->interruptStatistics[kInterruptAccountingFirstLevelCountIndex], 1);
412*a3bb9fccSApple OSS Distributions         }
413*a3bb9fccSApple OSS Distributions     }
414*a3bb9fccSApple OSS Distributions 
415855239e5SApple OSS Distributions     signalWorkAvailable();
416855239e5SApple OSS Distributions 
417855239e5SApple OSS Distributions 	if (trace)
418855239e5SApple OSS Distributions 	    IOTimeStampEndConstant(IODBG_INTES(IOINTES_SEMA), (uintptr_t) this, (uintptr_t) owner);
419c1dac77fSApple OSS Distributions }
420c1dac77fSApple OSS Distributions 
421c1dac77fSApple OSS Distributions void IOInterruptEventSource::disableInterruptOccurred
422c1dac77fSApple OSS Distributions     (void */*refcon*/, IOService *prov, int source)
423c1dac77fSApple OSS Distributions {
424855239e5SApple OSS Distributions 	bool trace = (gIOKitTrace & kIOTraceIntEventSource) ? true : false;
425c1dac77fSApple OSS Distributions 
426c1dac77fSApple OSS Distributions     prov->disableInterrupt(source);	/* disable the interrupt */
427c1dac77fSApple OSS Distributions 
428855239e5SApple OSS Distributions     IOStatisticsInterrupt();
429c1dac77fSApple OSS Distributions     producerCount++;
430c1dac77fSApple OSS Distributions 
431855239e5SApple OSS Distributions 	if (trace)
432855239e5SApple OSS Distributions 	    IOTimeStampStartConstant(IODBG_INTES(IOINTES_SEMA), (uintptr_t) this, (uintptr_t) owner);
433c1dac77fSApple OSS Distributions 
434*a3bb9fccSApple OSS Distributions     if (reserved->statistics) {
435*a3bb9fccSApple OSS Distributions         if (IA_GET_STATISTIC_ENABLED(kInterruptAccountingFirstLevelCountIndex)) {
436*a3bb9fccSApple OSS Distributions             IA_ADD_VALUE(&reserved->statistics->interruptStatistics[kInterruptAccountingFirstLevelCountIndex], 1);
437*a3bb9fccSApple OSS Distributions         }
438*a3bb9fccSApple OSS Distributions     }
439*a3bb9fccSApple OSS Distributions 
440855239e5SApple OSS Distributions     signalWorkAvailable();
441855239e5SApple OSS Distributions 
442855239e5SApple OSS Distributions 	if (trace)
443855239e5SApple OSS Distributions 	    IOTimeStampEndConstant(IODBG_INTES(IOINTES_SEMA), (uintptr_t) this, (uintptr_t) owner);
444c1dac77fSApple OSS Distributions }
445c1dac77fSApple OSS Distributions 
446c1dac77fSApple OSS Distributions void IOInterruptEventSource::interruptOccurred
447c1dac77fSApple OSS Distributions     (void *refcon, IOService *prov, int source)
448c1dac77fSApple OSS Distributions {
449c1dac77fSApple OSS Distributions     if (autoDisable && prov)
450c1dac77fSApple OSS Distributions         disableInterruptOccurred(refcon, prov, source);
451c1dac77fSApple OSS Distributions     else
452c1dac77fSApple OSS Distributions         normalInterruptOccurred(refcon, prov, source);
453c1dac77fSApple OSS Distributions }
454855239e5SApple OSS Distributions 
455855239e5SApple OSS Distributions IOReturn IOInterruptEventSource::warmCPU
456855239e5SApple OSS Distributions     (uint64_t abstime)
457855239e5SApple OSS Distributions {
458855239e5SApple OSS Distributions 
459855239e5SApple OSS Distributions 	return ml_interrupt_prewarm(abstime);
460855239e5SApple OSS Distributions }
461