1c1dac77fSApple OSS Distributions /*
2855239e5SApple OSS Distributions * Copyright (c) 1998-2010 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
29bb611c8fSApple OSS Distributions #define IOKIT_ENABLE_SHARED_PTR
30bb611c8fSApple OSS Distributions
31c1dac77fSApple OSS Distributions #include <IOKit/IOFilterInterruptEventSource.h>
32c1dac77fSApple OSS Distributions #include <IOKit/IOService.h>
33855239e5SApple OSS Distributions #include <IOKit/IOKitDebug.h>
34c1dac77fSApple OSS Distributions #include <IOKit/IOTimeStamp.h>
35c1dac77fSApple OSS Distributions #include <IOKit/IOWorkLoop.h>
36a3bb9fccSApple OSS Distributions #include <IOKit/IOInterruptAccountingPrivate.h>
37cc9a6355SApple OSS Distributions #include <libkern/Block.h>
38c1dac77fSApple OSS Distributions
39855239e5SApple OSS Distributions #if IOKITSTATS
40c1dac77fSApple OSS Distributions
41855239e5SApple OSS Distributions #define IOStatisticsInitializeCounter() \
42c1dac77fSApple OSS Distributions do { \
43855239e5SApple OSS Distributions IOStatistics::setCounterType(IOEventSource::reserved->counter, kIOStatisticsFilterInterruptEventSourceCounter); \
44c1dac77fSApple OSS Distributions } while (0)
45c1dac77fSApple OSS Distributions
46855239e5SApple OSS Distributions #define IOStatisticsInterrupt() \
47c1dac77fSApple OSS Distributions do { \
48855239e5SApple OSS Distributions IOStatistics::countInterrupt(IOEventSource::reserved->counter); \
49c1dac77fSApple OSS Distributions } while (0)
50c1dac77fSApple OSS Distributions
51855239e5SApple OSS Distributions #else
52c1dac77fSApple OSS Distributions
53855239e5SApple OSS Distributions #define IOStatisticsInitializeCounter()
54855239e5SApple OSS Distributions #define IOStatisticsInterrupt()
55855239e5SApple OSS Distributions
56855239e5SApple OSS Distributions #endif /* IOKITSTATS */
57c1dac77fSApple OSS Distributions
58c1dac77fSApple OSS Distributions #define super IOInterruptEventSource
59c1dac77fSApple OSS Distributions
60c1dac77fSApple OSS Distributions OSDefineMetaClassAndStructors
61c1dac77fSApple OSS Distributions (IOFilterInterruptEventSource, IOInterruptEventSource)
62c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOFilterInterruptEventSource, 0);
63c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOFilterInterruptEventSource, 1);
64c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOFilterInterruptEventSource, 2);
65c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOFilterInterruptEventSource, 3);
66c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOFilterInterruptEventSource, 4);
67c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOFilterInterruptEventSource, 5);
68c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOFilterInterruptEventSource, 6);
69c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOFilterInterruptEventSource, 7);
70c1dac77fSApple OSS Distributions
71c1dac77fSApple OSS Distributions /*
72c1dac77fSApple OSS Distributions * Implement the call throughs for the private protection conversion
73c1dac77fSApple OSS Distributions */
74a5e72196SApple OSS Distributions bool
init(OSObject * inOwner,Action inAction,IOService * inProvider,int inIntIndex)75a5e72196SApple OSS Distributions IOFilterInterruptEventSource::init(OSObject *inOwner,
76368ad365SApple OSS Distributions Action inAction,
77368ad365SApple OSS Distributions IOService *inProvider,
78368ad365SApple OSS Distributions int inIntIndex)
79c1dac77fSApple OSS Distributions {
80c1dac77fSApple OSS Distributions return false;
81c1dac77fSApple OSS Distributions }
82c1dac77fSApple OSS Distributions
83bb611c8fSApple OSS Distributions OSSharedPtr<IOInterruptEventSource>
interruptEventSource(OSObject * inOwner,Action inAction,IOService * inProvider,int inIntIndex)84c1dac77fSApple OSS Distributions IOFilterInterruptEventSource::interruptEventSource(OSObject *inOwner,
85c1dac77fSApple OSS Distributions Action inAction,
86c1dac77fSApple OSS Distributions IOService *inProvider,
87c1dac77fSApple OSS Distributions int inIntIndex)
88c1dac77fSApple OSS Distributions {
89a5e72196SApple OSS Distributions return NULL;
90c1dac77fSApple OSS Distributions }
91c1dac77fSApple OSS Distributions
92c1dac77fSApple OSS Distributions bool
init(OSObject * inOwner,Action inAction,Filter inFilterAction,IOService * inProvider,int inIntIndex)93c1dac77fSApple OSS Distributions IOFilterInterruptEventSource::init(OSObject *inOwner,
94c1dac77fSApple OSS Distributions Action inAction,
95c1dac77fSApple OSS Distributions Filter inFilterAction,
96c1dac77fSApple OSS Distributions IOService *inProvider,
97368ad365SApple OSS Distributions int inIntIndex)
98c1dac77fSApple OSS Distributions {
99a5e72196SApple OSS Distributions if (!super::init(inOwner, inAction, inProvider, inIntIndex)) {
100c1dac77fSApple OSS Distributions return false;
101a5e72196SApple OSS Distributions }
102c1dac77fSApple OSS Distributions
103a5e72196SApple OSS Distributions if (!inFilterAction) {
104c1dac77fSApple OSS Distributions return false;
105a5e72196SApple OSS Distributions }
106c1dac77fSApple OSS Distributions
107c1dac77fSApple OSS Distributions filterAction = inFilterAction;
108855239e5SApple OSS Distributions
109855239e5SApple OSS Distributions IOStatisticsInitializeCounter();
110855239e5SApple OSS Distributions
111c1dac77fSApple OSS Distributions return true;
112c1dac77fSApple OSS Distributions }
113c1dac77fSApple OSS Distributions
114bb611c8fSApple OSS Distributions OSSharedPtr<IOFilterInterruptEventSource>
115a5e72196SApple OSS Distributions IOFilterInterruptEventSource
filterInterruptEventSource(OSObject * inOwner,Action inAction,Filter inFilterAction,IOService * inProvider,int inIntIndex)116c1dac77fSApple OSS Distributions ::filterInterruptEventSource(OSObject *inOwner,
117c1dac77fSApple OSS Distributions Action inAction,
118c1dac77fSApple OSS Distributions Filter inFilterAction,
119c1dac77fSApple OSS Distributions IOService *inProvider,
120368ad365SApple OSS Distributions int inIntIndex)
121c1dac77fSApple OSS Distributions {
122bb611c8fSApple OSS Distributions OSSharedPtr<IOFilterInterruptEventSource> me = OSMakeShared<IOFilterInterruptEventSource>();
123c1dac77fSApple OSS Distributions
124c1dac77fSApple OSS Distributions if (me
125c1dac77fSApple OSS Distributions && !me->init(inOwner, inAction, inFilterAction, inProvider, inIntIndex)) {
126bb611c8fSApple OSS Distributions return nullptr;
127c1dac77fSApple OSS Distributions }
128c1dac77fSApple OSS Distributions
129c1dac77fSApple OSS Distributions return me;
130c1dac77fSApple OSS Distributions }
131c1dac77fSApple OSS Distributions
132cc9a6355SApple OSS Distributions
133bb611c8fSApple OSS Distributions OSSharedPtr<IOFilterInterruptEventSource>
134a5e72196SApple OSS Distributions IOFilterInterruptEventSource
filterInterruptEventSource(OSObject * inOwner,IOService * inProvider,int inIntIndex,ActionBlock inAction,FilterBlock inFilterAction)135cc9a6355SApple OSS Distributions ::filterInterruptEventSource(OSObject *inOwner,
136cc9a6355SApple OSS Distributions IOService *inProvider,
137cc9a6355SApple OSS Distributions int inIntIndex,
138cc9a6355SApple OSS Distributions ActionBlock inAction,
139cc9a6355SApple OSS Distributions FilterBlock inFilterAction)
140cc9a6355SApple OSS Distributions {
141bb611c8fSApple OSS Distributions OSSharedPtr<IOFilterInterruptEventSource> me = OSMakeShared<IOFilterInterruptEventSource>();
142cc9a6355SApple OSS Distributions
143cc9a6355SApple OSS Distributions FilterBlock filter = Block_copy(inFilterAction);
144a5e72196SApple OSS Distributions if (!filter) {
145bb611c8fSApple OSS Distributions return nullptr;
146a5e72196SApple OSS Distributions }
147cc9a6355SApple OSS Distributions
148cc9a6355SApple OSS Distributions if (me
149*5c2921b0SApple OSS Distributions && !me->init(inOwner, (Action) NULL, (Filter) (void (*)(void))filter, inProvider, inIntIndex)) {
150cc9a6355SApple OSS Distributions Block_release(filter);
151bb611c8fSApple OSS Distributions return nullptr;
152cc9a6355SApple OSS Distributions }
153cc9a6355SApple OSS Distributions me->flags |= kFilterBlock;
154cc9a6355SApple OSS Distributions me->setActionBlock((IOEventSource::ActionBlock) inAction);
155cc9a6355SApple OSS Distributions
156cc9a6355SApple OSS Distributions return me;
157cc9a6355SApple OSS Distributions }
158cc9a6355SApple OSS Distributions
159cc9a6355SApple OSS Distributions
160a5e72196SApple OSS Distributions void
free(void)161a5e72196SApple OSS Distributions IOFilterInterruptEventSource::free( void )
162cc9a6355SApple OSS Distributions {
163a5e72196SApple OSS Distributions if ((kFilterBlock & flags) && filterActionBlock) {
164a5e72196SApple OSS Distributions Block_release(filterActionBlock);
165a5e72196SApple OSS Distributions }
166cc9a6355SApple OSS Distributions
167cc9a6355SApple OSS Distributions super::free();
168cc9a6355SApple OSS Distributions }
169cc9a6355SApple OSS Distributions
170a5e72196SApple OSS Distributions void
signalInterrupt()171a5e72196SApple OSS Distributions IOFilterInterruptEventSource::signalInterrupt()
172c1dac77fSApple OSS Distributions {
173855239e5SApple OSS Distributions bool trace = (gIOKitTrace & kIOTraceIntEventSource) ? true : false;
174c1dac77fSApple OSS Distributions
175855239e5SApple OSS Distributions IOStatisticsInterrupt();
176c1dac77fSApple OSS Distributions producerCount++;
177c1dac77fSApple OSS Distributions
178a5e72196SApple OSS Distributions if (trace) {
17976e12aa3SApple OSS Distributions IOTimeStampStartConstant(IODBG_INTES(IOINTES_SEMA), VM_KERNEL_ADDRHIDE(this), VM_KERNEL_ADDRHIDE(owner));
180a5e72196SApple OSS Distributions }
181855239e5SApple OSS Distributions
182c1dac77fSApple OSS Distributions signalWorkAvailable();
183855239e5SApple OSS Distributions
184a5e72196SApple OSS Distributions if (trace) {
18576e12aa3SApple OSS Distributions IOTimeStampEndConstant(IODBG_INTES(IOINTES_SEMA), VM_KERNEL_ADDRHIDE(this), VM_KERNEL_ADDRHIDE(owner));
186a5e72196SApple OSS Distributions }
187c1dac77fSApple OSS Distributions }
188c1dac77fSApple OSS Distributions
189c1dac77fSApple OSS Distributions
190c1dac77fSApple OSS Distributions IOFilterInterruptEventSource::Filter
getFilterAction() const191c1dac77fSApple OSS Distributions IOFilterInterruptEventSource::getFilterAction() const
192c1dac77fSApple OSS Distributions {
193a5e72196SApple OSS Distributions if (kFilterBlock & flags) {
194a5e72196SApple OSS Distributions return NULL;
195a5e72196SApple OSS Distributions }
196c1dac77fSApple OSS Distributions return filterAction;
197c1dac77fSApple OSS Distributions }
198c1dac77fSApple OSS Distributions
199cc9a6355SApple OSS Distributions IOFilterInterruptEventSource::FilterBlock
getFilterActionBlock() const200cc9a6355SApple OSS Distributions IOFilterInterruptEventSource::getFilterActionBlock() const
201cc9a6355SApple OSS Distributions {
202a5e72196SApple OSS Distributions if (kFilterBlock & flags) {
203a5e72196SApple OSS Distributions return filterActionBlock;
204a5e72196SApple OSS Distributions }
205a5e72196SApple OSS Distributions return NULL;
206cc9a6355SApple OSS Distributions }
207c1dac77fSApple OSS Distributions
208a5e72196SApple OSS Distributions void
normalInterruptOccurred(void *,IOService *,int)209a5e72196SApple OSS Distributions IOFilterInterruptEventSource::normalInterruptOccurred
210c1dac77fSApple OSS Distributions (void */*refcon*/, IOService */*prov*/, int /*source*/)
211c1dac77fSApple OSS Distributions {
212c1dac77fSApple OSS Distributions bool filterRes;
213a3bb9fccSApple OSS Distributions uint64_t startTime = 0;
214a3bb9fccSApple OSS Distributions uint64_t endTime = 0;
215855239e5SApple OSS Distributions bool trace = (gIOKitTrace & kIOTraceIntEventSource) ? true : false;
216c1dac77fSApple OSS Distributions
217a5e72196SApple OSS Distributions if (trace) {
218855239e5SApple OSS Distributions IOTimeStampStartConstant(IODBG_INTES(IOINTES_FILTER),
21976e12aa3SApple OSS Distributions VM_KERNEL_UNSLIDE(filterAction), VM_KERNEL_ADDRHIDE(owner), VM_KERNEL_ADDRHIDE(this), VM_KERNEL_ADDRHIDE(workLoop));
220a5e72196SApple OSS Distributions }
221c1dac77fSApple OSS Distributions
222a3bb9fccSApple OSS Distributions if (IOInterruptEventSource::reserved->statistics) {
223a5e72196SApple OSS Distributions if (IA_GET_STATISTIC_ENABLED(kInterruptAccountingFirstLevelTimeIndex)
224a5e72196SApple OSS Distributions || IOInterruptEventSource::reserved->statistics->enablePrimaryTimestamp) {
225a3bb9fccSApple OSS Distributions startTime = mach_absolute_time();
226a3bb9fccSApple OSS Distributions }
227a5e72196SApple OSS Distributions if (IOInterruptEventSource::reserved->statistics->enablePrimaryTimestamp) {
228a5e72196SApple OSS Distributions IOInterruptEventSource::reserved->statistics->primaryTimestamp = startTime;
229a5e72196SApple OSS Distributions }
230a3bb9fccSApple OSS Distributions }
231a3bb9fccSApple OSS Distributions
232855239e5SApple OSS Distributions // Call the filter.
233a5e72196SApple OSS Distributions if (kFilterBlock & flags) {
234a5e72196SApple OSS Distributions filterRes = (filterActionBlock)(this);
235a5e72196SApple OSS Distributions } else {
236a5e72196SApple OSS Distributions filterRes = (*filterAction)(owner, this);
237a5e72196SApple OSS Distributions }
238855239e5SApple OSS Distributions
239a3bb9fccSApple OSS Distributions if (IOInterruptEventSource::reserved->statistics) {
240a3bb9fccSApple OSS Distributions if (IA_GET_STATISTIC_ENABLED(kInterruptAccountingFirstLevelCountIndex)) {
241a3bb9fccSApple OSS Distributions IA_ADD_VALUE(&IOInterruptEventSource::reserved->statistics->interruptStatistics[kInterruptAccountingFirstLevelCountIndex], 1);
242a3bb9fccSApple OSS Distributions }
243a3bb9fccSApple OSS Distributions
244a3bb9fccSApple OSS Distributions if (IA_GET_STATISTIC_ENABLED(kInterruptAccountingFirstLevelTimeIndex)) {
245a3bb9fccSApple OSS Distributions endTime = mach_absolute_time();
246a3bb9fccSApple OSS Distributions IA_ADD_VALUE(&IOInterruptEventSource::reserved->statistics->interruptStatistics[kInterruptAccountingFirstLevelTimeIndex], endTime - startTime);
247a3bb9fccSApple OSS Distributions }
248a3bb9fccSApple OSS Distributions }
249a3bb9fccSApple OSS Distributions
250a5e72196SApple OSS Distributions if (trace) {
251855239e5SApple OSS Distributions IOTimeStampEndConstant(IODBG_INTES(IOINTES_FILTER),
25276e12aa3SApple OSS Distributions VM_KERNEL_ADDRHIDE(filterAction), VM_KERNEL_ADDRHIDE(owner),
25376e12aa3SApple OSS Distributions VM_KERNEL_ADDRHIDE(this), VM_KERNEL_ADDRHIDE(workLoop));
254c1dac77fSApple OSS Distributions }
255c1dac77fSApple OSS Distributions
256a5e72196SApple OSS Distributions if (filterRes) {
257a5e72196SApple OSS Distributions signalInterrupt();
258a5e72196SApple OSS Distributions }
259a5e72196SApple OSS Distributions }
260a5e72196SApple OSS Distributions
261a5e72196SApple OSS Distributions void
disableInterruptOccurred(void *,IOService * prov,int source)262a5e72196SApple OSS Distributions IOFilterInterruptEventSource::disableInterruptOccurred
263c1dac77fSApple OSS Distributions (void */*refcon*/, IOService *prov, int source)
264c1dac77fSApple OSS Distributions {
265c1dac77fSApple OSS Distributions bool filterRes;
266a3bb9fccSApple OSS Distributions uint64_t startTime = 0;
267a3bb9fccSApple OSS Distributions uint64_t endTime = 0;
268855239e5SApple OSS Distributions bool trace = (gIOKitTrace & kIOTraceIntEventSource) ? true : false;
269c1dac77fSApple OSS Distributions
270a5e72196SApple OSS Distributions if (trace) {
271855239e5SApple OSS Distributions IOTimeStampStartConstant(IODBG_INTES(IOINTES_FILTER),
27276e12aa3SApple OSS Distributions VM_KERNEL_UNSLIDE(filterAction), VM_KERNEL_ADDRHIDE(owner), VM_KERNEL_ADDRHIDE(this), VM_KERNEL_ADDRHIDE(workLoop));
273a5e72196SApple OSS Distributions }
274c1dac77fSApple OSS Distributions
275a3bb9fccSApple OSS Distributions if (IOInterruptEventSource::reserved->statistics) {
276a5e72196SApple OSS Distributions if (IA_GET_STATISTIC_ENABLED(kInterruptAccountingFirstLevelTimeIndex)
277a5e72196SApple OSS Distributions || IOInterruptEventSource::reserved->statistics->enablePrimaryTimestamp) {
278a3bb9fccSApple OSS Distributions startTime = mach_absolute_time();
279a3bb9fccSApple OSS Distributions }
280a5e72196SApple OSS Distributions if (IOInterruptEventSource::reserved->statistics->enablePrimaryTimestamp) {
281a5e72196SApple OSS Distributions IOInterruptEventSource::reserved->statistics->primaryTimestamp = startTime;
282a5e72196SApple OSS Distributions }
283a3bb9fccSApple OSS Distributions }
284a3bb9fccSApple OSS Distributions
285855239e5SApple OSS Distributions // Call the filter.
286a5e72196SApple OSS Distributions if (kFilterBlock & flags) {
287a5e72196SApple OSS Distributions filterRes = (filterActionBlock)(this);
288a5e72196SApple OSS Distributions } else {
289a5e72196SApple OSS Distributions filterRes = (*filterAction)(owner, this);
290a5e72196SApple OSS Distributions }
291855239e5SApple OSS Distributions
292a3bb9fccSApple OSS Distributions if (IOInterruptEventSource::reserved->statistics) {
293a3bb9fccSApple OSS Distributions if (IA_GET_STATISTIC_ENABLED(kInterruptAccountingFirstLevelCountIndex)) {
294a3bb9fccSApple OSS Distributions IA_ADD_VALUE(&IOInterruptEventSource::reserved->statistics->interruptStatistics[kInterruptAccountingFirstLevelCountIndex], 1);
295a3bb9fccSApple OSS Distributions }
296a3bb9fccSApple OSS Distributions
297a3bb9fccSApple OSS Distributions if (IA_GET_STATISTIC_ENABLED(kInterruptAccountingFirstLevelTimeIndex)) {
298a3bb9fccSApple OSS Distributions endTime = mach_absolute_time();
299a3bb9fccSApple OSS Distributions IA_ADD_VALUE(&IOInterruptEventSource::reserved->statistics->interruptStatistics[kInterruptAccountingFirstLevelTimeIndex], endTime - startTime);
300a3bb9fccSApple OSS Distributions }
301a3bb9fccSApple OSS Distributions }
302a3bb9fccSApple OSS Distributions
303a5e72196SApple OSS Distributions if (trace) {
304855239e5SApple OSS Distributions IOTimeStampEndConstant(IODBG_INTES(IOINTES_FILTER),
30576e12aa3SApple OSS Distributions VM_KERNEL_UNSLIDE(filterAction), VM_KERNEL_ADDRHIDE(owner), VM_KERNEL_ADDRHIDE(this), VM_KERNEL_ADDRHIDE(workLoop));
306a5e72196SApple OSS Distributions }
307c1dac77fSApple OSS Distributions
308c1dac77fSApple OSS Distributions if (filterRes) {
309c1dac77fSApple OSS Distributions prov->disableInterrupt(source); /* disable the interrupt */
310c1dac77fSApple OSS Distributions signalInterrupt();
311c1dac77fSApple OSS Distributions }
312c1dac77fSApple OSS Distributions }
313