#ifndef _IOKIT_APPLE8259PIC_H
#define _IOKIT_APPLE8259PIC_H
#include <IOKit/IOInterrupts.h>
#include <IOKit/IOInterruptController.h>
#include <libkern/c++/OSContainers.h>
#define kClockIRQ 0
#define kPIC1BasePort 0x20
#define kPIC2BasePort 0xa0
#define kPIC1TriggerTypePort 0x4d0
#define kPIC2TriggerTypePort 0x4d1
#define kPICCmdPortOffset 0
#define kPICDataPortOffset 1
#define kEOICommand 0x20
#define kPICSlaveID 2 // Slave ID for second PIC
#define kNumVectors 16
#define IS_SLAVE_VECTOR(x) ((x) & 8)
#define kPIC_ICW1(x) ((x) + kPICCmdPortOffset)
#define kPIC_ICW1_MBO 0x10 // must be one
#define kPIC_ICW1_LTIM 0x08 // level/edge triggered mode
#define kPIC_ICW1_ADI 0x04 // 4/8 byte call address interval
#define kPIC_ICW1_SNGL 0x02 // single/cascade mode
#define kPIC_ICW1_IC4 0x01 // ICW4 needed/not needed
#define kPIC_ICW2(x) ((x) + kPICDataPortOffset)
#define kPIC_ICW3(x) ((x) + kPICDataPortOffset)
#define kPIC_ICW4(x) ((x) + kPICDataPortOffset)
#define kPIC_ICW4_SFNM 0x10 // special fully nested mode
#define kPIC_ICW4_BUF 0x08 // buffered mode
#define kPIC_ICW4_MS 0x04 // master/slave
#define kPIC_ICW4_AEOI 0x02 // automatic end of interrupt mode
#define kPIC_ICW4_uPM 0x01 // 8088 (vs. 8085) operation
#define kPIC_OCW1(x) ((x) + kPICDataPortOffset)
#define kPIC_OCW2(x) ((x) + kPICCmdPortOffset)
#define kPIC_OCW2_R 0x80 // rotation
#define kPIC_OCW2_SL 0x40 // specific
#define kPIC_OCW2_EOI 0x20
#define kPIC_OCW2_LEVEL(x) ((x) & 0x07)
#define kPIC_OCW3(x) ((x) + kPICCmdPortOffset)
#define kPIC_OCW3_ESMM 0x40 // special mask mode
#define kPIC_OCW3_SMM 0x20
#define kPIC_OCW3_MBO 0x08 // must be one
#define kPIC_OCW3_P 0x04 // poll
#define kPIC_OCW3_RR 0x02
#define kPIC_OCW3_RIS 0x01
static __inline__ UInt8 inb( UInt16 port )
{
UInt8 data;
__asm__ volatile ( "inb %1, %0"
: "=a" (data)
: "d" (port));
return data;
}
static __inline__ void outb( UInt16 port, UInt8 data )
{
__asm__ volatile ( "outb %1, %0"
:
: "d" (port), "a" (data));
}
#define Apple8259PIC Apple8259PICInterruptController
class Apple8259PIC : public IOInterruptController
{
OSDeclareDefaultStructors( Apple8259PICInterruptController );
protected:
UInt16 _interruptMasks;
UInt16 _interruptTriggerTypes;
IOSimpleLock * _interruptLock;
const OSSymbol * _handleSleepWakeFunction;
const OSSymbol * _setVectorTypeFunction;
inline void writeInterruptMask( long irq )
{
if ( IS_SLAVE_VECTOR(irq) )
outb( kPIC_OCW1(kPIC2BasePort), _interruptMasks >> 8 );
else
outb( kPIC_OCW1(kPIC1BasePort), _interruptMasks & 0xff );
}
inline void disableInterrupt( long irq )
{
_interruptMasks |= (1 << irq);
writeInterruptMask(irq);
}
inline void enableInterrupt( long irq )
{
_interruptMasks &= ~(1 << irq);
writeInterruptMask(irq);
}
inline void ackInterrupt( long irq )
{
if ( IS_SLAVE_VECTOR(irq) )
outb( kPIC_OCW2(kPIC2BasePort), kEOICommand );
outb( kPIC_OCW2(kPIC1BasePort), kEOICommand );
}
virtual void initializePIC( UInt16 port,
UInt8 icw1, UInt8 icw2,
UInt8 icw3, UInt8 icw4 );
virtual void prepareForSleep( void );
virtual void resumeFromSleep( void );
virtual IOReturn setVectorType( long vectorNumber, long type );
virtual void free( void );
public:
virtual bool start( IOService * provider );
virtual IOReturn getInterruptType( IOService * nub,
int source,
int * interruptType );
virtual int getVectorType( long vectorNumber,
IOInterruptVector * vector);
virtual IOInterruptAction getInterruptHandlerAddress( void );
virtual IOReturn handleInterrupt( void * refCon,
IOService * nub,
int source );
virtual bool vectorCanBeShared( long vectorNumber,
IOInterruptVector * vector );
virtual void initVector( long vectorNumber,
IOInterruptVector * vector );
virtual void disableVectorHard( long vectorNumber,
IOInterruptVector * vector );
virtual void enableVector( long vectorNumber,
IOInterruptVector * vector );
virtual IOReturn callPlatformFunction( const OSSymbol * function,
bool waitForFunction,
void * param1, void * param2,
void * param3, void * param4 );
};
#endif