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