|
|
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: Michael Burg
26: */
27:
28:
29: #include <IOKit/IOLib.h>
30: #include <IOKit/IOService.h>
31: #include <IOKit/IODeviceMemory.h>
32: #include <IOKit/IOPlatformExpert.h>
33:
34: #include "AppleIntelClassicPIC.h"
35:
36: #define outb(port, datum) \
37: __asm__ volatile("outb %b0, %1" : : "a" ((unsigned char)(datum)), "i" ((unsigned short)port))
38:
39: #define send_duel_eoi(port1, port2) \
40: __asm__ volatile("outb %b0, %1 ; outb %b0, %2" : : "a" (kEOICommand), "i" ((unsigned short)port1), "i" ((unsigned short)port2))
41:
42:
43: #define kIntelReservedIntVectors 0x40
44:
45: extern "C" {
46: /* HACK, HACK, HACK.. for rtclock on intel.. FIXME */
47: extern void (*IOKitRegisterInterruptHook)(void *, int, int);
48: };
49:
50: static AppleIntelClassicPIC *picObjectHook;
51:
52: IOInterruptController *gIntelInterruptController;
53:
54: extern OSSymbol *gIntelPICName;
55:
56: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
57:
58: #undef super
59: #define super IOInterruptController
60:
61: OSDefineMetaClassAndStructors(AppleIntelClassicPIC, IOInterruptController);
62:
63: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
64:
65: bool AppleIntelClassicPIC::start(IOService *provider)
66: {
67: IOInterruptAction handler;
68: int cnt;
69:
70: if (!super::start(provider))
71: return false;
72:
73:
74: // Allocate the memory for the vectors.
75: vectors = (IOInterruptVector *)IOMalloc(kNumVectors *
76: sizeof(IOInterruptVector));
77: if (vectors == NULL) return false;
78:
79: bzero(vectors, kNumVectors * sizeof(IOInterruptVector));
80:
81:
82: // Allocate locks for the vectors.
83: for (cnt = 0; cnt < kNumVectors; cnt++) {
84: vectors[cnt].interruptLock = IOLockAlloc();
85: if (vectors[cnt].interruptLock == NULL) {
86: for (cnt = 0; cnt < kNumVectors; cnt++) {
87: if (vectors[cnt].interruptLock != NULL)
88: IOLockFree(vectors[cnt].interruptLock);
89: }
90: return false;
91: }
92: }
93:
94: maskInterrupts = 0xffff & ~(1<<kPICSlaveID); /* Mask out the interrupts except for the casacde line */
95:
96: /* Setup the interrupt controller.. */
97: /* Original code taken from FreeBSD's sys/i386/isa/intr_machdep.c */
98:
99: /* initialize 8259's */
100: outb(kPIC1BasePort, 0x11); /* reset; program device, four bytes */
101:
102: /* starting at this vector index */
103: outb(kPIC1BasePort+kPICDataPortOffset, kIntelReservedIntVectors);
104:
105: outb(kPIC1BasePort+kPICDataPortOffset, kPICSlaveIRQID); /* slave on line 7 */
106:
107: outb(kPIC1BasePort+kPICDataPortOffset, 1); /* 8086 mode */
108:
109: outb(kPIC1BasePort+kPICDataPortOffset, 0xff); /* leave interrupts masked */
110: outb(kPIC1BasePort, 0x0a); /* default to IRR on read */
111: outb(kPIC1BasePort, 0xc0 | (3 - 1)); /* pri order 3-7, 0-2 (com2 first) */
112:
113: outb(kPIC2BasePort, 0x11); /* reset; program device, four bytes */
114: outb(kPIC2BasePort+kPICDataPortOffset, kIntelReservedIntVectors+8); /* staring at this vector index */
115: outb(kPIC2BasePort+kPICDataPortOffset, kPICSlaveID); /* my slave id is 7 */
116: outb(kPIC2BasePort+kPICDataPortOffset,1); /* 8086 mode */
117: outb(kPIC2BasePort+kPICDataPortOffset, 0xff); /* leave interrupts masked */
118: outb(kPIC2BasePort, 0x0a); /* default to IRR on read */
119:
120: // Primary interrupt controller
121: getPlatform()->setCPUInterruptProperties(provider);
122:
123: // setup clock interrupt back door hook
124: IOKitRegisterInterruptHook = getRegisterInterruptHookAddress();
125: picObjectHook = this;
126:
127: // register the interrupt handler so it can receive interrupts.
128: handler = getInterruptHandlerAddress();
129: if (provider->registerInterrupt(0, this, handler, 0) != kIOReturnSuccess)
130: panic("AppleIntelClassicPIC: Failed to install platform interrupt handler");
131: provider->enableInterrupt(0);
132:
133: // Register this interrupt controller so clients can find it.
134: getPlatform()->registerInterruptController(gIntelPICName, this) ;
135: gIntelInterruptController = this;
136:
137: return true;
138: }
139:
140: IOReturn AppleIntelClassicPIC::getInterruptType(IOService */*nub*/,
141: int /*source*/,
142: int *interruptType)
143: {
144: if (interruptType == 0) return kIOReturnBadArgument;
145:
146: *interruptType = kIOInterruptTypeEdge;
147:
148: return kIOReturnSuccess;
149: }
150:
151: IOInterruptAction AppleIntelClassicPIC::getInterruptHandlerAddress(void)
152: {
153: void *value;
154:
155: value = (void *) &AppleIntelClassicPIC::handleInterrupt;
156:
157: return (IOInterruptAction)(value);
158: }
159:
160: IOReturn AppleIntelClassicPIC::handleInterrupt(void *savedState,
161: IOService */*nub*/,
162: int vectorNumber)
163: {
164: IOInterruptVector *vector;
165: typedef void (*IntelClockFuncType)(void *);
166: IntelClockFuncType clockFunc;
167:
168: vectorNumber -= kIntelReservedIntVectors;
169:
170: if (vectorNumber >= kNumVectors) return kIOReturnSuccess;
171:
172: maskInterrupts |= (1 << vectorNumber);
173:
174: if (vectorNumber > 7) {
175: /* Mask out interrupt */
176: outb(kPIC2BasePort+kPICDataPortOffset, maskInterrupts >> 8);
177:
178: /* Acknowledge interrupt */
179: send_duel_eoi(kPIC2BasePort+kPICCmdPortOffset, kPIC1BasePort+kPICCmdPortOffset);
180: } else {
181: outb(kPIC1BasePort+kPICDataPortOffset, maskInterrupts & 0xff);
182: outb(kPIC1BasePort+kPICCmdPortOffset, kEOICommand);
183: }
184:
185: vector = &vectors[vectorNumber];
186:
187: vector->interruptActive = 1;
188: if (!vector->interruptDisabledSoft) {
189: if (vector->interruptRegistered) {
190: if (vectorNumber == kClockIRQ) {
191: clockFunc = (IntelClockFuncType) vector->handler;
192: clockFunc(savedState);
193: } else {
194: vector->handler(vector->target, vector->refCon,
195: vector->nub, vector->source);
196: }
197: maskInterrupts &= ~(1 << vectorNumber);
198: }
199: } else {
200: printf("*** DISABLING INT %d\n", vectorNumber);
201: // Hard disable the source.
202: vector->interruptDisabledHard = 1;
203: disableVectorHard(vectorNumber, vector);
204: }
205:
206: if (vectorNumber > 7)
207: outb(kPIC2BasePort+kPICDataPortOffset, maskInterrupts >> 8);
208: else
209: outb(kPIC1BasePort+kPICDataPortOffset, maskInterrupts & 0xff );
210:
211:
212: vector->interruptActive = 0;
213:
214: return kIOReturnSuccess;
215: }
216:
217: bool AppleIntelClassicPIC::vectorCanBeShared(long /*vectorNumber*/, IOInterruptVector */*vector*/)
218: {
219: /* FIXME! Need to account for PCI sharable interrupts */
220: return false;
221: }
222:
223: void AppleIntelClassicPIC::initVector(long /*vectorNumber*/,
224: IOInterruptVector * /*vector*/)
225: {
226: /* Do nothing.. */
227: }
228:
229: void AppleIntelClassicPIC::disableVectorHard(long vectorNumber, IOInterruptVector */*vector*/)
230: {
231: if (vectorNumber == kPICSlaveID) /* Sorry, cacade interrupt cannot be disable */
232: return;
233:
234: maskInterrupts |= (1<<vectorNumber);
235:
236: /* Load up mask interrupts */
237: if (vectorNumber > 7)
238: outb(kPIC2BasePort + kPICDataPortOffset, maskInterrupts >> 8);
239: else
240: outb(kPIC1BasePort + kPICDataPortOffset, maskInterrupts & 0xff);
241: }
242:
243: void AppleIntelClassicPIC::enableVector(long vectorNumber,
244: IOInterruptVector *vector)
245: {
246: maskInterrupts &= ~(1<<vectorNumber);
247:
248: /* Load up mask interrupts */
249: if (vectorNumber > 7)
250: outb(kPIC2BasePort + kPICDataPortOffset, maskInterrupts >> 8);
251: else
252: outb(kPIC1BasePort + kPICDataPortOffset, maskInterrupts & 0xff);
253: }
254:
255: static void AppleIntelClassicPICRegisterHook(void *func, int source, int isclock)
256: {
257: picObjectHook->registerInterruptHook(func, source, isclock);
258: }
259:
260: void AppleIntelClassicPIC::registerInterruptHook(void *func, int source, int isclock)
261: {
262: IOInterruptVector *vector;
263:
264: vector = &vectors[source];
265:
266: vector->handler = (IOInterruptHandler) func;
267: vector->interruptRegistered = TRUE;
268: vector->interruptDisabledSoft = FALSE;
269: vector->interruptDisabledHard = FALSE;
270:
271: enableVector(source, vector);
272: }
273:
274:
275: IOKitInterruptHookType
276: AppleIntelClassicPIC::getRegisterInterruptHookAddress(void)
277: {
278: void *value;
279: value = (void *) AppleIntelClassicPICRegisterHook;
280: return (IOKitInterruptHookType) value;
281: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.