]>
Commit | Line | Data |
---|---|---|
1c79356b A |
1 | /* |
2 | * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
e5568f75 A |
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. | |
1c79356b | 11 | * |
e5568f75 A |
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 | |
1c79356b A |
14 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
15 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
e5568f75 A |
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. | |
1c79356b A |
19 | * |
20 | * @APPLE_LICENSE_HEADER_END@ | |
21 | */ | |
22 | /* | |
23 | * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. | |
24 | * | |
25 | * DRI: Josh de Cesare | |
26 | * | |
27 | */ | |
28 | ||
29 | ||
30 | #if __ppc__ | |
31 | #include <ppc/proc_reg.h> | |
32 | #endif | |
33 | ||
34 | #include <IOKit/IOLib.h> | |
35 | #include <IOKit/IOService.h> | |
36 | #include <IOKit/IOPlatformExpert.h> | |
37 | #include <IOKit/IOInterrupts.h> | |
38 | #include <IOKit/IOInterruptController.h> | |
39 | ||
40 | ||
41 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | |
42 | ||
43 | #define super IOService | |
44 | ||
45 | OSDefineMetaClassAndAbstractStructors(IOInterruptController, IOService); | |
46 | ||
47 | OSMetaClassDefineReservedUnused(IOInterruptController, 0); | |
48 | OSMetaClassDefineReservedUnused(IOInterruptController, 1); | |
49 | OSMetaClassDefineReservedUnused(IOInterruptController, 2); | |
50 | OSMetaClassDefineReservedUnused(IOInterruptController, 3); | |
51 | OSMetaClassDefineReservedUnused(IOInterruptController, 4); | |
52 | OSMetaClassDefineReservedUnused(IOInterruptController, 5); | |
53 | ||
54 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | |
55 | ||
56 | IOReturn IOInterruptController::registerInterrupt(IOService *nub, int source, | |
57 | void *target, | |
58 | IOInterruptHandler handler, | |
59 | void *refCon) | |
60 | { | |
61 | IOInterruptSource *interruptSources; | |
62 | long vectorNumber; | |
63 | IOInterruptVector *vector; | |
64 | long wasDisabledSoft; | |
65 | IOReturn error; | |
66 | OSData *vectorData; | |
67 | IOService *originalNub; | |
68 | int originalSource; | |
69 | ||
70 | interruptSources = nub->_interruptSources; | |
71 | vectorData = interruptSources[source].vectorData; | |
72 | vectorNumber = *(long *)vectorData->getBytesNoCopy(); | |
73 | vector = &vectors[vectorNumber]; | |
74 | ||
75 | // Get the lock for this vector. | |
76 | IOTakeLock(vector->interruptLock); | |
77 | ||
78 | // If this vector is already in use, and can be shared, | |
79 | // register as a shared interrupt. | |
80 | if (vector->interruptRegistered) { | |
81 | if (!vectorCanBeShared(vectorNumber, vector)) { | |
82 | IOUnlock(vector->interruptLock); | |
83 | return kIOReturnNoResources; | |
84 | } | |
85 | ||
86 | // If this vector is not already shared, break it out. | |
87 | if (vector->sharedController == 0) { | |
88 | // Make the IOShareInterruptController instance | |
89 | vector->sharedController = new IOSharedInterruptController; | |
90 | if (vector->sharedController == 0) { | |
91 | IOUnlock(vector->interruptLock); | |
92 | return kIOReturnNoMemory; | |
93 | } | |
94 | ||
95 | // Save the nub and source for the original consumer. | |
96 | originalNub = vector->nub; | |
97 | originalSource = vector->source; | |
98 | ||
ac5ea4a9 A |
99 | // Physically disable the interrupt, but mark it as being enables in the hardware. |
100 | // The interruptDisabledSoft now indicates the driver's request for enablement. | |
101 | disableVectorHard(vectorNumber, vector); | |
102 | vector->interruptDisabledHard = 0; | |
1c79356b A |
103 | |
104 | // Initialize the new shared interrupt controller. | |
105 | error = vector->sharedController->initInterruptController(this, | |
106 | vectorData); | |
107 | // If the IOSharedInterruptController could not be initalized, | |
108 | // put the original consumor's interrupt back to normal and | |
109 | // get rid of whats left of the shared controller. | |
110 | if (error != kIOReturnSuccess) { | |
111 | enableInterrupt(originalNub, originalSource); | |
112 | vector->sharedController->release(); | |
113 | vector->sharedController = 0; | |
114 | IOUnlock(vector->interruptLock); | |
115 | return error; | |
116 | } | |
117 | ||
118 | // Try to register the original consumer on the shared controller. | |
119 | error = vector->sharedController->registerInterrupt(originalNub, | |
120 | originalSource, | |
121 | vector->target, | |
122 | vector->handler, | |
123 | vector->refCon); | |
124 | // If the original consumer could not be moved to the shared controller, | |
125 | // put the original consumor's interrupt back to normal and | |
126 | // get rid of whats left of the shared controller. | |
127 | if (error != kIOReturnSuccess) { | |
ac5ea4a9 A |
128 | // Save the driver's interrupt enablement state. |
129 | wasDisabledSoft = vector->interruptDisabledSoft; | |
130 | ||
131 | // Make the interrupt really hard disabled. | |
132 | vector->interruptDisabledSoft = 1; | |
133 | vector->interruptDisabledHard = 1; | |
134 | ||
135 | // Enable the original consumer's interrupt if needed. | |
136 | if (!wasDisabledSoft) originalNub->enableInterrupt(originalSource); | |
1c79356b | 137 | enableInterrupt(originalNub, originalSource); |
ac5ea4a9 | 138 | |
1c79356b A |
139 | vector->sharedController->release(); |
140 | vector->sharedController = 0; | |
141 | IOUnlock(vector->interruptLock); | |
142 | return error; | |
143 | } | |
144 | ||
145 | // Fill in vector with the shared controller's info. | |
146 | vector->handler = (IOInterruptHandler)vector->sharedController->getInterruptHandlerAddress(); | |
147 | vector->nub = vector->sharedController; | |
148 | vector->source = 0; | |
149 | vector->target = vector->sharedController; | |
150 | vector->refCon = 0; | |
151 | ||
ac5ea4a9 A |
152 | // Save the driver's interrupt enablement state. |
153 | wasDisabledSoft = vector->interruptDisabledSoft; | |
154 | ||
155 | // Make the interrupt really hard disabled. | |
156 | vector->interruptDisabledSoft = 1; | |
157 | vector->interruptDisabledHard = 1; | |
158 | ||
1c79356b A |
159 | // Enable the original consumer's interrupt if needed. |
160 | if (!wasDisabledSoft) originalNub->enableInterrupt(originalSource); | |
161 | } | |
162 | ||
163 | error = vector->sharedController->registerInterrupt(nub, source, target, | |
164 | handler, refCon); | |
165 | IOUnlock(vector->interruptLock); | |
166 | return error; | |
167 | } | |
168 | ||
169 | // Fill in vector with the client's info. | |
170 | vector->handler = handler; | |
171 | vector->nub = nub; | |
172 | vector->source = source; | |
173 | vector->target = target; | |
174 | vector->refCon = refCon; | |
175 | ||
176 | // Do any specific initalization for this vector. | |
177 | initVector(vectorNumber, vector); | |
178 | ||
179 | // Get the vector ready. It starts hard disabled. | |
180 | vector->interruptDisabledHard = 1; | |
181 | vector->interruptDisabledSoft = 1; | |
182 | vector->interruptRegistered = 1; | |
183 | ||
184 | IOUnlock(vector->interruptLock); | |
185 | return kIOReturnSuccess; | |
186 | } | |
187 | ||
188 | IOReturn IOInterruptController::unregisterInterrupt(IOService *nub, int source) | |
189 | { | |
190 | IOInterruptSource *interruptSources; | |
191 | long vectorNumber; | |
192 | IOInterruptVector *vector; | |
193 | OSData *vectorData; | |
194 | ||
195 | interruptSources = nub->_interruptSources; | |
196 | vectorData = interruptSources[source].vectorData; | |
197 | vectorNumber = *(long *)vectorData->getBytesNoCopy(); | |
198 | vector = &vectors[vectorNumber]; | |
199 | ||
200 | // Get the lock for this vector. | |
201 | IOTakeLock(vector->interruptLock); | |
202 | ||
203 | // Return success if it is not already registered | |
204 | if (!vector->interruptRegistered) { | |
205 | IOUnlock(vector->interruptLock); | |
206 | return kIOReturnSuccess; | |
207 | } | |
208 | ||
209 | // Soft disable the source. | |
210 | disableInterrupt(nub, source); | |
211 | ||
212 | // Turn the source off at hardware. | |
213 | disableVectorHard(vectorNumber, vector); | |
214 | ||
215 | // Clear all the storage for the vector except for interruptLock. | |
216 | vector->interruptActive = 0; | |
217 | vector->interruptDisabledSoft = 0; | |
218 | vector->interruptDisabledHard = 0; | |
219 | vector->interruptRegistered = 0; | |
220 | vector->nub = 0; | |
221 | vector->source = 0; | |
222 | vector->handler = 0; | |
223 | vector->target = 0; | |
224 | vector->refCon = 0; | |
225 | ||
226 | IOUnlock(vector->interruptLock); | |
227 | return kIOReturnSuccess; | |
228 | } | |
229 | ||
230 | IOReturn IOInterruptController::getInterruptType(IOService *nub, int source, | |
231 | int *interruptType) | |
232 | { | |
233 | IOInterruptSource *interruptSources; | |
234 | long vectorNumber; | |
235 | IOInterruptVector *vector; | |
236 | OSData *vectorData; | |
237 | ||
238 | if (interruptType == 0) return kIOReturnBadArgument; | |
239 | ||
240 | interruptSources = nub->_interruptSources; | |
241 | vectorData = interruptSources[source].vectorData; | |
242 | vectorNumber = *(long *)vectorData->getBytesNoCopy(); | |
243 | vector = &vectors[vectorNumber]; | |
244 | ||
245 | *interruptType = getVectorType(vectorNumber, vector); | |
246 | ||
247 | return kIOReturnSuccess; | |
248 | } | |
249 | ||
250 | IOReturn IOInterruptController::enableInterrupt(IOService *nub, int source) | |
251 | { | |
252 | IOInterruptSource *interruptSources; | |
253 | long vectorNumber; | |
254 | IOInterruptVector *vector; | |
255 | OSData *vectorData; | |
256 | ||
257 | interruptSources = nub->_interruptSources; | |
258 | vectorData = interruptSources[source].vectorData; | |
259 | vectorNumber = *(long *)vectorData->getBytesNoCopy(); | |
260 | vector = &vectors[vectorNumber]; | |
261 | ||
262 | if (vector->interruptDisabledSoft) { | |
263 | vector->interruptDisabledSoft = 0; | |
0b4e3aa0 A |
264 | #if __ppc__ |
265 | sync(); | |
266 | isync(); | |
267 | #endif | |
1c79356b | 268 | |
0b4e3aa0 A |
269 | if (!getPlatform()->atInterruptLevel()) { |
270 | while (vector->interruptActive); | |
271 | #if __ppc__ | |
272 | isync(); | |
273 | #endif | |
274 | } | |
1c79356b A |
275 | if (vector->interruptDisabledHard) { |
276 | vector->interruptDisabledHard = 0; | |
277 | ||
278 | enableVector(vectorNumber, vector); | |
279 | } | |
280 | } | |
281 | ||
282 | return kIOReturnSuccess; | |
283 | } | |
284 | ||
285 | IOReturn IOInterruptController::disableInterrupt(IOService *nub, int source) | |
286 | { | |
287 | IOInterruptSource *interruptSources; | |
288 | long vectorNumber; | |
289 | IOInterruptVector *vector; | |
290 | OSData *vectorData; | |
291 | ||
292 | interruptSources = nub->_interruptSources; | |
293 | vectorData = interruptSources[source].vectorData; | |
294 | vectorNumber = *(long *)vectorData->getBytesNoCopy(); | |
295 | vector = &vectors[vectorNumber]; | |
296 | ||
297 | vector->interruptDisabledSoft = 1; | |
298 | #if __ppc__ | |
299 | sync(); | |
300 | isync(); | |
301 | #endif | |
302 | ||
303 | if (!getPlatform()->atInterruptLevel()) { | |
304 | while (vector->interruptActive); | |
305 | #if __ppc__ | |
306 | isync(); | |
307 | #endif | |
308 | } | |
309 | ||
310 | return kIOReturnSuccess; | |
311 | } | |
312 | ||
313 | IOReturn IOInterruptController::causeInterrupt(IOService *nub, int source) | |
314 | { | |
315 | IOInterruptSource *interruptSources; | |
316 | long vectorNumber; | |
317 | IOInterruptVector *vector; | |
318 | OSData *vectorData; | |
319 | ||
320 | interruptSources = nub->_interruptSources; | |
321 | vectorData = interruptSources[source].vectorData; | |
322 | vectorNumber = *(long *)vectorData->getBytesNoCopy(); | |
323 | vector = &vectors[vectorNumber]; | |
324 | ||
325 | causeVector(vectorNumber, vector); | |
326 | ||
327 | return kIOReturnSuccess; | |
328 | } | |
329 | ||
330 | IOInterruptAction IOInterruptController::getInterruptHandlerAddress(void) | |
331 | { | |
332 | return 0; | |
333 | } | |
334 | ||
335 | IOReturn IOInterruptController::handleInterrupt(void *refCon, IOService *nub, | |
336 | int source) | |
337 | { | |
338 | return kIOReturnInvalid; | |
339 | } | |
340 | ||
341 | ||
342 | // Methods to be overridden for simplifed interrupt controller subclasses. | |
343 | ||
344 | bool IOInterruptController::vectorCanBeShared(long /*vectorNumber*/, | |
345 | IOInterruptVector */*vector*/) | |
346 | { | |
347 | return false; | |
348 | } | |
349 | ||
350 | void IOInterruptController::initVector(long /*vectorNumber*/, | |
351 | IOInterruptVector */*vector*/) | |
352 | { | |
353 | } | |
354 | ||
355 | int IOInterruptController::getVectorType(long /*vectorNumber*/, | |
356 | IOInterruptVector */*vector*/) | |
357 | { | |
358 | return kIOInterruptTypeEdge; | |
359 | } | |
360 | ||
361 | void IOInterruptController::disableVectorHard(long /*vectorNumber*/, | |
362 | IOInterruptVector */*vector*/) | |
363 | { | |
364 | } | |
365 | ||
366 | void IOInterruptController::enableVector(long /*vectorNumber*/, | |
367 | IOInterruptVector */*vector*/) | |
368 | { | |
369 | } | |
370 | ||
371 | void IOInterruptController::causeVector(long /*vectorNumber*/, | |
372 | IOInterruptVector */*vector*/) | |
373 | { | |
374 | } | |
375 | ||
376 | ||
377 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | |
378 | ||
379 | #undef super | |
380 | #define super IOInterruptController | |
381 | ||
382 | OSDefineMetaClassAndStructors(IOSharedInterruptController, IOInterruptController); | |
383 | ||
384 | OSMetaClassDefineReservedUnused(IOSharedInterruptController, 0); | |
385 | OSMetaClassDefineReservedUnused(IOSharedInterruptController, 1); | |
386 | OSMetaClassDefineReservedUnused(IOSharedInterruptController, 2); | |
387 | OSMetaClassDefineReservedUnused(IOSharedInterruptController, 3); | |
388 | ||
389 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | |
390 | ||
391 | IOReturn IOSharedInterruptController::initInterruptController(IOInterruptController *parentController, OSData *parentSource) | |
392 | { | |
393 | int cnt, interruptType; | |
394 | IOReturn error; | |
395 | ||
396 | if (!super::init()) | |
397 | return kIOReturnNoResources; | |
398 | ||
399 | // Set provider to this so enable/disable nub stuff works. | |
400 | provider = this; | |
401 | ||
402 | // Allocate the IOInterruptSource so this can act like a nub. | |
403 | _interruptSources = (IOInterruptSource *)IOMalloc(sizeof(IOInterruptSource)); | |
404 | if (_interruptSources == 0) return kIOReturnNoMemory; | |
405 | _numInterruptSources = 1; | |
406 | ||
407 | // Set up the IOInterruptSource to point at this. | |
408 | _interruptSources[0].interruptController = parentController; | |
409 | _interruptSources[0].vectorData = parentSource; | |
410 | ||
411 | sourceIsLevel = false; | |
412 | error = provider->getInterruptType(0, &interruptType); | |
413 | if (error == kIOReturnSuccess) { | |
414 | if (interruptType & kIOInterruptTypeLevel) | |
415 | sourceIsLevel = true; | |
416 | } | |
417 | ||
418 | // Allocate the memory for the vectors | |
ac5ea4a9 | 419 | numVectors = 32; // For now a constant number. |
1c79356b A |
420 | vectors = (IOInterruptVector *)IOMalloc(numVectors * sizeof(IOInterruptVector)); |
421 | if (vectors == NULL) { | |
422 | IOFree(_interruptSources, sizeof(IOInterruptSource)); | |
423 | return kIOReturnNoMemory; | |
424 | } | |
425 | bzero(vectors, numVectors * sizeof(IOInterruptVector)); | |
426 | ||
427 | // Allocate the lock for the controller. | |
428 | controllerLock = IOSimpleLockAlloc(); | |
429 | if (controllerLock == 0) return kIOReturnNoResources; | |
430 | ||
431 | // Allocate locks for the vectors. | |
432 | for (cnt = 0; cnt < numVectors; cnt++) { | |
433 | vectors[cnt].interruptLock = IOLockAlloc(); | |
434 | if (vectors[cnt].interruptLock == NULL) { | |
435 | for (cnt = 0; cnt < numVectors; cnt++) { | |
436 | if (vectors[cnt].interruptLock != NULL) | |
437 | IOLockFree(vectors[cnt].interruptLock); | |
438 | } | |
439 | return kIOReturnNoResources; | |
440 | } | |
441 | } | |
442 | ||
443 | vectorsRegistered = 0; | |
444 | vectorsEnabled = 0; | |
445 | controllerDisabled = 1; | |
446 | ||
447 | return kIOReturnSuccess; | |
448 | } | |
449 | ||
450 | IOReturn IOSharedInterruptController::registerInterrupt(IOService *nub, | |
451 | int source, | |
452 | void *target, | |
453 | IOInterruptHandler handler, | |
454 | void *refCon) | |
455 | { | |
456 | IOInterruptSource *interruptSources; | |
457 | long vectorNumber; | |
458 | IOInterruptVector *vector = 0; | |
459 | OSData *vectorData; | |
460 | IOInterruptState interruptState; | |
461 | ||
462 | interruptSources = nub->_interruptSources; | |
463 | ||
464 | // Find a free vector. | |
465 | vectorNumber = numVectors; | |
466 | while (vectorsRegistered != numVectors) { | |
467 | for (vectorNumber = 0; vectorNumber < numVectors; vectorNumber++) { | |
468 | vector = &vectors[vectorNumber]; | |
469 | ||
470 | // Get the lock for this vector. | |
471 | IOTakeLock(vector->interruptLock); | |
472 | ||
473 | // Is it unregistered? | |
474 | if (!vector->interruptRegistered) break; | |
475 | ||
476 | // Move along to the next one. | |
477 | IOUnlock(vector->interruptLock); | |
478 | } | |
479 | ||
480 | if (vectorNumber != numVectors) break; | |
481 | } | |
482 | ||
483 | // Could not find a free one, so give up. | |
484 | if (vectorNumber == numVectors) { | |
485 | return kIOReturnNoResources; | |
486 | } | |
487 | ||
488 | // Create the vectorData for the IOInterruptSource. | |
489 | vectorData = OSData::withBytes(&vectorNumber, sizeof(vectorNumber)); | |
490 | if (vectorData == 0) { | |
491 | return kIOReturnNoMemory; | |
492 | } | |
493 | ||
494 | // Fill in the IOInterruptSource with the controller's info. | |
495 | interruptSources[source].interruptController = this; | |
496 | interruptSources[source].vectorData = vectorData; | |
497 | ||
498 | // Fill in vector with the client's info. | |
499 | vector->handler = handler; | |
500 | vector->nub = nub; | |
501 | vector->source = source; | |
502 | vector->target = target; | |
503 | vector->refCon = refCon; | |
504 | ||
505 | // Get the vector ready. It start soft disabled. | |
506 | vector->interruptDisabledSoft = 1; | |
507 | vector->interruptRegistered = 1; | |
508 | ||
509 | interruptState = IOSimpleLockLockDisableInterrupt(controllerLock); | |
510 | vectorsRegistered++; | |
511 | IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState); | |
512 | ||
513 | IOUnlock(vector->interruptLock); | |
514 | return kIOReturnSuccess; | |
515 | } | |
516 | ||
517 | IOReturn IOSharedInterruptController::unregisterInterrupt(IOService *nub, | |
518 | int source) | |
519 | { | |
520 | IOInterruptSource *interruptSources; | |
521 | long vectorNumber; | |
522 | IOInterruptVector *vector; | |
523 | OSData *vectorData; | |
524 | IOInterruptState interruptState;; | |
525 | ||
526 | interruptSources = nub->_interruptSources; | |
527 | vectorData = interruptSources[source].vectorData; | |
528 | vectorNumber = *(long *)vectorData->getBytesNoCopy(); | |
529 | vector = &vectors[vectorNumber]; | |
530 | ||
531 | // Get the lock for this vector. | |
532 | IOTakeLock(vector->interruptLock); | |
533 | ||
534 | // Return success if it is not already registered | |
535 | if (!vector->interruptRegistered) { | |
536 | IOUnlock(vector->interruptLock); | |
537 | return kIOReturnSuccess; | |
538 | } | |
539 | ||
540 | // Soft disable the source. | |
541 | disableInterrupt(nub, source); | |
542 | ||
543 | // Clear all the storage for the vector except for interruptLock. | |
544 | vector->interruptActive = 0; | |
545 | vector->interruptDisabledSoft = 0; | |
546 | vector->interruptDisabledHard = 0; | |
547 | vector->interruptRegistered = 0; | |
548 | vector->nub = 0; | |
549 | vector->source = 0; | |
550 | vector->handler = 0; | |
551 | vector->target = 0; | |
552 | vector->refCon = 0; | |
553 | ||
554 | interruptState = IOSimpleLockLockDisableInterrupt(controllerLock); | |
555 | vectorsRegistered--; | |
556 | IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState); | |
557 | ||
558 | IOUnlock(vector->interruptLock); | |
559 | return kIOReturnSuccess; | |
560 | } | |
561 | ||
562 | IOReturn IOSharedInterruptController::getInterruptType(IOService */*nub*/, | |
563 | int /*source*/, | |
564 | int *interruptType) | |
565 | { | |
566 | return provider->getInterruptType(0, interruptType); | |
567 | } | |
568 | ||
569 | IOReturn IOSharedInterruptController::enableInterrupt(IOService *nub, | |
570 | int source) | |
571 | { | |
572 | IOInterruptSource *interruptSources; | |
573 | long vectorNumber; | |
574 | IOInterruptVector *vector; | |
575 | OSData *vectorData; | |
14353aa8 | 576 | IOInterruptState interruptState; |
1c79356b A |
577 | |
578 | interruptSources = nub->_interruptSources; | |
579 | vectorData = interruptSources[source].vectorData; | |
580 | vectorNumber = *(long *)vectorData->getBytesNoCopy(); | |
581 | vector = &vectors[vectorNumber]; | |
582 | ||
14353aa8 A |
583 | interruptState = IOSimpleLockLockDisableInterrupt(controllerLock); |
584 | if (!vector->interruptDisabledSoft) { | |
1c79356b | 585 | IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState); |
14353aa8 A |
586 | return kIOReturnSuccess; |
587 | } | |
588 | ||
589 | vector->interruptDisabledSoft = 0; | |
590 | vectorsEnabled++; | |
591 | IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState); | |
592 | ||
593 | if (controllerDisabled && (vectorsEnabled == vectorsRegistered)) { | |
594 | controllerDisabled = 0; | |
595 | provider->enableInterrupt(0); | |
1c79356b A |
596 | } |
597 | ||
598 | return kIOReturnSuccess; | |
599 | } | |
600 | ||
601 | IOReturn IOSharedInterruptController::disableInterrupt(IOService *nub, | |
602 | int source) | |
603 | { | |
604 | IOInterruptSource *interruptSources; | |
605 | long vectorNumber; | |
606 | IOInterruptVector *vector; | |
607 | OSData *vectorData; | |
14353aa8 | 608 | IOInterruptState interruptState; |
1c79356b A |
609 | |
610 | interruptSources = nub->_interruptSources; | |
611 | vectorData = interruptSources[source].vectorData; | |
612 | vectorNumber = *(long *)vectorData->getBytesNoCopy(); | |
613 | vector = &vectors[vectorNumber]; | |
614 | ||
14353aa8 | 615 | interruptState = IOSimpleLockLockDisableInterrupt(controllerLock); |
1c79356b A |
616 | if (!vector->interruptDisabledSoft) { |
617 | vector->interruptDisabledSoft = 1; | |
618 | #if __ppc__ | |
619 | sync(); | |
620 | isync(); | |
621 | #endif | |
1c79356b | 622 | vectorsEnabled--; |
1c79356b | 623 | } |
14353aa8 | 624 | IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState); |
1c79356b A |
625 | |
626 | if (!getPlatform()->atInterruptLevel()) { | |
627 | while (vector->interruptActive); | |
628 | #if __ppc__ | |
629 | isync(); | |
630 | #endif | |
631 | } | |
632 | ||
633 | return kIOReturnSuccess; | |
634 | } | |
635 | ||
636 | IOInterruptAction IOSharedInterruptController::getInterruptHandlerAddress(void) | |
637 | { | |
638 | return (IOInterruptAction)&IOSharedInterruptController::handleInterrupt; | |
639 | } | |
640 | ||
641 | IOReturn IOSharedInterruptController::handleInterrupt(void * /*refCon*/, | |
642 | IOService * nub, | |
643 | int /*source*/) | |
644 | { | |
645 | long vectorNumber; | |
646 | IOInterruptVector *vector; | |
647 | ||
648 | for (vectorNumber = 0; vectorNumber < numVectors; vectorNumber++) { | |
649 | vector = &vectors[vectorNumber]; | |
650 | ||
651 | vector->interruptActive = 1; | |
652 | #if __ppc__ | |
653 | sync(); | |
654 | isync(); | |
655 | #endif | |
656 | if (!vector->interruptDisabledSoft) { | |
657 | #if __ppc__ | |
658 | isync(); | |
659 | #endif | |
660 | ||
661 | // Call the handler if it exists. | |
662 | if (vector->interruptRegistered) { | |
663 | vector->handler(vector->target, vector->refCon, | |
664 | vector->nub, vector->source); | |
665 | } | |
666 | } | |
667 | ||
668 | vector->interruptActive = 0; | |
669 | } | |
670 | ||
671 | // if any of the vectors are dissabled, then dissable this controller. | |
672 | IOSimpleLockLock(controllerLock); | |
673 | if (vectorsEnabled != vectorsRegistered) { | |
674 | nub->disableInterrupt(0); | |
675 | controllerDisabled = 1; | |
676 | } | |
677 | IOSimpleLockUnlock(controllerLock); | |
678 | ||
679 | return kIOReturnSuccess; | |
680 | } | |
681 |