2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
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
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.
23 * @APPLE_LICENSE_HEADER_END@
26 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
31 #include <architecture/i386/pio.h>
32 #include <IOKit/IOLib.h>
33 #include <IOKit/IOPlatformExpert.h>
34 #include "AppleIntelClassicPIC.h"
36 // This must agree with the trap number reported by the low-level
37 // interrupt handler (osfmk/i386/locore.s).
39 #define kIntelReservedIntVectors 0x40
41 extern OSSymbol
* gIntelPICName
;
43 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
46 #define super IOInterruptController
48 OSDefineMetaClassAndStructors(AppleIntelClassicPIC
, IOInterruptController
);
50 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
52 bool AppleIntelClassicPIC::start(IOService
* provider
)
54 IOInterruptAction handler
;
56 if ( super::start(provider
) == false ) return false;
58 // Allocate the memory for the vectors.
60 vectors
= (IOInterruptVector
*) IOMalloc( kNumVectors
*
61 sizeof(IOInterruptVector
) );
62 if ( vectors
== NULL
) return false;
64 bzero(vectors
, kNumVectors
* sizeof(IOInterruptVector
));
66 // Allocate locks for the vectors.
68 for ( int cnt
= 0; cnt
< kNumVectors
; cnt
++ )
70 vectors
[cnt
].interruptLock
= IOLockAlloc();
72 if ( vectors
[cnt
].interruptLock
== NULL
)
78 // Mask out the interrupts except for the casacde line.
80 maskInterrupts
= 0xffff & ~(1 << kPICSlaveID
);
82 // Initialize master PIC.
84 initializePIC( kPIC1BasePort
,
85 /* ICW1 */ kPIC_ICW1_IC4
,
86 /* ICW2 */ kIntelReservedIntVectors
,
87 /* ICW3 */ (1 << kPICSlaveID
),
88 /* ICW4 */ kPIC_ICW4_uPM
);
90 // Write to OCW1, OCW3, OCW2.
91 // The priority order is changed to (highest to lowest)
93 // The default priority after initialization is (highest to lowest)
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
|
100 kPIC_OCW2_LEVEL(2) );
102 // Initialize slave PIC.
104 initializePIC( kPIC2BasePort
,
105 /* ICW1 */ kPIC_ICW1_IC4
,
106 /* ICW2 */ kIntelReservedIntVectors
+ 8,
107 /* ICW3 */ kPICSlaveID
,
108 /* ICW4 */ kPIC_ICW4_uPM
);
110 // Write to OCW1, and OCW3.
112 outb( kPIC_OCW1(kPIC2BasePort
), maskInterrupts
>> 8 );
113 outb( kPIC_OCW3(kPIC2BasePort
), kPIC_OCW3_MBO
| kPIC_OCW3_RR
);
115 // Record trigger type.
117 triggerTypes
= inb( kPIC1TriggerTypePort
) |
118 ( inb( kPIC2TriggerTypePort
) << 8 );
120 // Primary interrupt controller
122 getPlatform()->setCPUInterruptProperties(provider
);
124 // Register the interrupt handler function so it can service interrupts.
126 handler
= getInterruptHandlerAddress();
127 if ( provider
->registerInterrupt(0, this, handler
, 0) != kIOReturnSuccess
)
128 panic("AppleIntelClassicPIC: Failed to install platform interrupt handler");
130 provider
->enableInterrupt(0);
132 // Register this interrupt controller so clients can find it.
134 getPlatform()->registerInterruptController(gIntelPICName
, this);
139 //---------------------------------------------------------------------------
140 // Free the interrupt controller object. Deallocate all resources.
142 void AppleIntelClassicPIC::free(void)
146 for ( int cnt
= 0; cnt
< kNumVectors
; cnt
++ )
148 if (vectors
[cnt
].interruptLock
)
149 IOLockFree(vectors
[cnt
].interruptLock
);
152 IOFree( vectors
, kNumVectors
* sizeof(IOInterruptVector
) );
159 //---------------------------------------------------------------------------
160 // Initialize the PIC by sending the Initialization Command Words (ICW).
162 void AppleIntelClassicPIC::initializePIC( UInt16 port
,
163 UInt8 icw1
, UInt8 icw2
,
164 UInt8 icw3
, UInt8 icw4
)
166 // Initialize 8259's. Start the initialization sequence by
167 // issuing ICW1 (Initialization Command Word 1).
168 // Bit 4 must be set.
170 outb( kPIC_ICW1(port
), kPIC_ICW1_MBO
| icw1
);
173 // Upper 5 bits of the interrupt vector address. The lower three
174 // bits are set according to the interrupt level serviced.
176 outb( kPIC_ICW2(port
), icw2
);
178 // ICW3 (Master Device)
179 // Set a 1 bit for each IR line that has a slave.
181 outb( kPIC_ICW3(port
), icw3
);
185 outb( kPIC_ICW4(port
), icw4
);
188 //---------------------------------------------------------------------------
189 // Report whether the interrupt line is edge or level triggered.
191 int AppleIntelClassicPIC::getVectorType(long vectorNumber
,
192 IOInterruptVector
* vector
)
194 return getTriggerType(vectorNumber
);
197 //---------------------------------------------------------------------------
200 IOInterruptAction
AppleIntelClassicPIC::getInterruptHandlerAddress(void)
202 return (IOInterruptAction
) &AppleIntelClassicPIC::handleInterrupt
;
205 //---------------------------------------------------------------------------
206 // Handle an interrupt by servicing the 8259, and dispatch the
207 // handler associated with the interrupt vector.
209 IOReturn
AppleIntelClassicPIC::handleInterrupt(void * savedState
,
213 IOInterruptVector
* vector
;
216 typedef void (*IntelClockFuncType
)(void *);
217 IntelClockFuncType clockFunc
;
219 vectorNumber
= source
- kIntelReservedIntVectors
;
221 if (vectorNumber
>= kNumVectors
)
222 return kIOReturnSuccess
;
224 // Disable and ack interrupt.
226 disableInterrupt(vectorNumber
);
227 ackInterrupt( vectorNumber
);
229 // Process the interrupt.
231 vector
= &vectors
[vectorNumber
];
233 vector
->interruptActive
= 1;
235 if ( !vector
->interruptDisabledSoft
)
237 if ( vector
->interruptRegistered
)
239 // Call registered interrupt handler.
241 if (vectorNumber
== kClockIRQ
) // FIXME
243 clockFunc
= (IntelClockFuncType
) vector
->handler
;
244 clockFunc(savedState
);
248 vector
->handler(vector
->target
, vector
->refCon
,
249 vector
->nub
, vector
->source
);
252 // interruptDisabledSoft flag may be set by the
253 // handler to indicate that the interrupt should
256 if ( vector
->interruptDisabledSoft
)
258 // Already "hard" disabled, set interruptDisabledHard
261 vector
->interruptDisabledHard
= 1;
265 // Re-enable the interrupt line.
267 enableInterrupt(vectorNumber
);
273 vector
->interruptDisabledHard
= 1;
276 vector
->interruptActive
= 0;
278 return kIOReturnSuccess
;
281 //---------------------------------------------------------------------------
284 bool AppleIntelClassicPIC::vectorCanBeShared(long vectorNumber
,
285 IOInterruptVector
* vector
)
287 if ( getVectorType(vectorNumber
, vector
) == kIOInterruptTypeLevel
)
293 //---------------------------------------------------------------------------
296 void AppleIntelClassicPIC::initVector(long vectorNumber
,
297 IOInterruptVector
* vector
)
299 super::initVector(vectorNumber
, vector
);
302 //---------------------------------------------------------------------------
305 void AppleIntelClassicPIC::disableVectorHard(long vectorNumber
,
306 IOInterruptVector
* vector
)
308 // Sorry, cacade/slave interrupt line cannot be disable.
310 if (vectorNumber
== kPICSlaveID
) return;
312 disableInterrupt(vectorNumber
);
315 //---------------------------------------------------------------------------
318 void AppleIntelClassicPIC::enableVector(long vectorNumber
,
319 IOInterruptVector
* vector
)
321 enableInterrupt(vectorNumber
);