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