]> git.saurik.com Git - apple/xnu.git/blob - iokit/Drivers/platform/drvAppleIntelClassicPIC/PIC8259.cpp
xnu-344.49.tar.gz
[apple/xnu.git] / iokit / Drivers / platform / drvAppleIntelClassicPIC / PIC8259.cpp
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: 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 }