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