]>
Commit | Line | Data |
---|---|---|
1c79356b A |
1 | /* |
2 | * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
d7e50217 | 6 | * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. |
1c79356b | 7 | * |
d7e50217 A |
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 | |
1c79356b A |
17 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
18 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
d7e50217 A |
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. | |
1c79356b A |
22 | * |
23 | * @APPLE_LICENSE_HEADER_END@ | |
24 | */ | |
25 | /* | |
26 | * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. | |
27 | * | |
28 | * DRI: Michael Burg | |
29 | */ | |
30 | ||
31 | #include <architecture/i386/pio.h> | |
32 | #include <IOKit/IOLib.h> | |
33 | #include <IOKit/IOPlatformExpert.h> | |
34 | #include "AppleIntelClassicPIC.h" | |
35 | ||
36 | // This must agree with the trap number reported by the low-level | |
37 | // interrupt handler (osfmk/i386/locore.s). | |
38 | ||
39 | #define kIntelReservedIntVectors 0x40 | |
40 | ||
41 | extern OSSymbol * gIntelPICName; | |
42 | ||
43 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | |
44 | ||
45 | #undef super | |
46 | #define super IOInterruptController | |
47 | ||
48 | OSDefineMetaClassAndStructors(AppleIntelClassicPIC, IOInterruptController); | |
49 | ||
50 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | |
51 | ||
52 | bool AppleIntelClassicPIC::start(IOService * provider) | |
53 | { | |
54 | IOInterruptAction handler; | |
55 | ||
56 | if ( super::start(provider) == false ) return false; | |
57 | ||
58 | // Allocate the memory for the vectors. | |
59 | ||
60 | vectors = (IOInterruptVector *) IOMalloc( kNumVectors * | |
61 | sizeof(IOInterruptVector) ); | |
62 | if ( vectors == NULL ) return false; | |
63 | ||
64 | bzero(vectors, kNumVectors * sizeof(IOInterruptVector)); | |
65 | ||
66 | // Allocate locks for the vectors. | |
67 | ||
68 | for ( int cnt = 0; cnt < kNumVectors; cnt++ ) | |
69 | { | |
70 | vectors[cnt].interruptLock = IOLockAlloc(); | |
71 | ||
72 | if ( vectors[cnt].interruptLock == NULL ) | |
73 | { | |
74 | return false; | |
75 | } | |
76 | } | |
77 | ||
78 | // Mask out the interrupts except for the casacde line. | |
79 | ||
80 | maskInterrupts = 0xffff & ~(1 << kPICSlaveID); | |
81 | ||
82 | // Initialize master PIC. | |
83 | ||
84 | initializePIC( kPIC1BasePort, | |
85 | /* ICW1 */ kPIC_ICW1_IC4, | |
86 | /* ICW2 */ kIntelReservedIntVectors, | |
87 | /* ICW3 */ (1 << kPICSlaveID), | |
88 | /* ICW4 */ kPIC_ICW4_uPM ); | |
89 | ||
90 | // Write to OCW1, OCW3, OCW2. | |
91 | // The priority order is changed to (highest to lowest) | |
92 | // 3 4 5 6 7 0 1 2 | |
93 | // The default priority after initialization is (highest to lowest) | |
94 | // 0 1 2 3 4 5 6 7 | |
95 | ||
96 | outb( kPIC_OCW1(kPIC1BasePort), maskInterrupts & 0xff ); | |
97 | outb( kPIC_OCW3(kPIC1BasePort), kPIC_OCW3_MBO | kPIC_OCW3_RR ); | |
98 | outb( kPIC_OCW2(kPIC1BasePort), kPIC_OCW2_R | | |
99 | kPIC_OCW2_SL | | |
100 | kPIC_OCW2_LEVEL(2) ); | |
101 | ||
102 | // Initialize slave PIC. | |
103 | ||
104 | initializePIC( kPIC2BasePort, | |
105 | /* ICW1 */ kPIC_ICW1_IC4, | |
106 | /* ICW2 */ kIntelReservedIntVectors + 8, | |
107 | /* ICW3 */ kPICSlaveID, | |
108 | /* ICW4 */ kPIC_ICW4_uPM ); | |
109 | ||
110 | // Write to OCW1, and OCW3. | |
111 | ||
112 | outb( kPIC_OCW1(kPIC2BasePort), maskInterrupts >> 8 ); | |
113 | outb( kPIC_OCW3(kPIC2BasePort), kPIC_OCW3_MBO | kPIC_OCW3_RR ); | |
114 | ||
115 | // Record trigger type. | |
116 | ||
117 | triggerTypes = inb( kPIC1TriggerTypePort ) | | |
118 | ( inb( kPIC2TriggerTypePort ) << 8 ); | |
119 | ||
120 | // Primary interrupt controller | |
121 | ||
122 | getPlatform()->setCPUInterruptProperties(provider); | |
123 | ||
124 | // Register the interrupt handler function so it can service interrupts. | |
125 | ||
126 | handler = getInterruptHandlerAddress(); | |
127 | if ( provider->registerInterrupt(0, this, handler, 0) != kIOReturnSuccess ) | |
128 | panic("AppleIntelClassicPIC: Failed to install platform interrupt handler"); | |
129 | ||
130 | provider->enableInterrupt(0); | |
131 | ||
132 | // Register this interrupt controller so clients can find it. | |
133 | ||
134 | getPlatform()->registerInterruptController(gIntelPICName, this); | |
135 | ||
136 | return true; | |
137 | } | |
138 | ||
139 | //--------------------------------------------------------------------------- | |
140 | // Free the interrupt controller object. Deallocate all resources. | |
141 | ||
142 | void AppleIntelClassicPIC::free(void) | |
143 | { | |
144 | if ( vectors ) | |
145 | { | |
146 | for ( int cnt = 0; cnt < kNumVectors; cnt++ ) | |
147 | { | |
148 | if (vectors[cnt].interruptLock) | |
149 | IOLockFree(vectors[cnt].interruptLock); | |
150 | } | |
151 | ||
152 | IOFree( vectors, kNumVectors * sizeof(IOInterruptVector) ); | |
153 | vectors = 0; | |
154 | } | |
155 | ||
156 | super::free(); | |
157 | } | |
158 | ||
159 | //--------------------------------------------------------------------------- | |
160 | // Initialize the PIC by sending the Initialization Command Words (ICW). | |
161 | ||
162 | void AppleIntelClassicPIC::initializePIC( UInt16 port, | |
163 | UInt8 icw1, UInt8 icw2, | |
164 | UInt8 icw3, UInt8 icw4 ) | |
165 | { | |
166 | // Initialize 8259's. Start the initialization sequence by | |
167 | // issuing ICW1 (Initialization Command Word 1). | |
168 | // Bit 4 must be set. | |
169 | ||
170 | outb( kPIC_ICW1(port), kPIC_ICW1_MBO | icw1 ); | |
171 | ||
172 | // ICW2 | |
173 | // Upper 5 bits of the interrupt vector address. The lower three | |
174 | // bits are set according to the interrupt level serviced. | |
175 | ||
176 | outb( kPIC_ICW2(port), icw2 ); | |
177 | ||
178 | // ICW3 (Master Device) | |
179 | // Set a 1 bit for each IR line that has a slave. | |
180 | ||
181 | outb( kPIC_ICW3(port), icw3 ); | |
182 | ||
183 | // ICW4 | |
184 | ||
185 | outb( kPIC_ICW4(port), icw4 ); | |
186 | } | |
187 | ||
188 | //--------------------------------------------------------------------------- | |
189 | // Report whether the interrupt line is edge or level triggered. | |
190 | ||
191 | int AppleIntelClassicPIC::getVectorType(long vectorNumber, | |
192 | IOInterruptVector * vector) | |
193 | { | |
194 | return getTriggerType(vectorNumber); | |
195 | } | |
196 | ||
197 | //--------------------------------------------------------------------------- | |
198 | // | |
199 | ||
200 | IOInterruptAction AppleIntelClassicPIC::getInterruptHandlerAddress(void) | |
201 | { | |
202 | return (IOInterruptAction) &AppleIntelClassicPIC::handleInterrupt; | |
203 | } | |
204 | ||
205 | //--------------------------------------------------------------------------- | |
206 | // Handle an interrupt by servicing the 8259, and dispatch the | |
207 | // handler associated with the interrupt vector. | |
208 | ||
209 | IOReturn AppleIntelClassicPIC::handleInterrupt(void * savedState, | |
210 | IOService * nub, | |
211 | int source) | |
212 | { | |
213 | IOInterruptVector * vector; | |
214 | long vectorNumber; | |
215 | ||
216 | typedef void (*IntelClockFuncType)(void *); | |
217 | IntelClockFuncType clockFunc; | |
218 | ||
219 | vectorNumber = source - kIntelReservedIntVectors; | |
220 | ||
221 | if (vectorNumber >= kNumVectors) | |
222 | return kIOReturnSuccess; | |
223 | ||
224 | // Disable and ack interrupt. | |
225 | ||
226 | disableInterrupt(vectorNumber); | |
227 | ackInterrupt( vectorNumber); | |
228 | ||
229 | // Process the interrupt. | |
230 | ||
231 | vector = &vectors[vectorNumber]; | |
232 | ||
233 | vector->interruptActive = 1; | |
234 | ||
235 | if ( !vector->interruptDisabledSoft ) | |
236 | { | |
237 | if ( vector->interruptRegistered ) | |
238 | { | |
239 | // Call registered interrupt handler. | |
240 | ||
241 | if (vectorNumber == kClockIRQ) // FIXME | |
242 | { | |
243 | clockFunc = (IntelClockFuncType) vector->handler; | |
244 | clockFunc(savedState); | |
245 | } | |
246 | else | |
247 | { | |
248 | vector->handler(vector->target, vector->refCon, | |
249 | vector->nub, vector->source); | |
250 | } | |
251 | ||
252 | // interruptDisabledSoft flag may be set by the | |
253 | // handler to indicate that the interrupt should | |
254 | // be disabled. | |
255 | ||
256 | if ( vector->interruptDisabledSoft ) | |
257 | { | |
258 | // Already "hard" disabled, set interruptDisabledHard | |
259 | // to indicate this. | |
260 | ||
261 | vector->interruptDisabledHard = 1; | |
262 | } | |
263 | else | |
264 | { | |
265 | // Re-enable the interrupt line. | |
266 | ||
267 | enableInterrupt(vectorNumber); | |
268 | } | |
269 | } | |
270 | } | |
271 | else | |
272 | { | |
273 | vector->interruptDisabledHard = 1; | |
274 | } | |
275 | ||
276 | vector->interruptActive = 0; | |
277 | ||
278 | return kIOReturnSuccess; | |
279 | } | |
280 | ||
281 | //--------------------------------------------------------------------------- | |
282 | // | |
283 | ||
284 | bool AppleIntelClassicPIC::vectorCanBeShared(long vectorNumber, | |
285 | IOInterruptVector * vector) | |
286 | { | |
287 | if ( getVectorType(vectorNumber, vector) == kIOInterruptTypeLevel ) | |
288 | return true; | |
289 | else | |
290 | return false; | |
291 | } | |
292 | ||
293 | //--------------------------------------------------------------------------- | |
294 | // | |
295 | ||
296 | void AppleIntelClassicPIC::initVector(long vectorNumber, | |
297 | IOInterruptVector * vector) | |
298 | { | |
299 | super::initVector(vectorNumber, vector); | |
300 | } | |
301 | ||
302 | //--------------------------------------------------------------------------- | |
303 | // | |
304 | ||
305 | void AppleIntelClassicPIC::disableVectorHard(long vectorNumber, | |
306 | IOInterruptVector * vector) | |
307 | { | |
308 | // Sorry, cacade/slave interrupt line cannot be disable. | |
309 | ||
310 | if (vectorNumber == kPICSlaveID) return; | |
311 | ||
312 | disableInterrupt(vectorNumber); | |
313 | } | |
314 | ||
315 | //--------------------------------------------------------------------------- | |
316 | // | |
317 | ||
318 | void AppleIntelClassicPIC::enableVector(long vectorNumber, | |
319 | IOInterruptVector * vector) | |
320 | { | |
321 | enableInterrupt(vectorNumber); | |
322 | } |