'******************************************************************************
'* 
'* PROGRAMMABLE INTERRUPT CONTROLLERS i8259 x 2 (PC/AT cascade) (CHIP DEVICE)
'*
'* Used to provide IRQ processing
'*
'* Supported platform/bus: X86
'* 
'* Version history:
'*  - 2007-2009 by WadiM (initial emulation and fixes)
'*
'****************************************************************************** 

//DEBUG.ON 'uncomment to enable debug messages (can be slow for hi-freq events)
//DIRECT.OFF 'uncomment to always use scripted implementation (non-internal)

//device interface support
public use object DEVICE

'internal implementation (direct)
public use internal "PICS8259AT"

//device name
DeviceName="PICs i8259AT"
DebugName="PICs_I8259AT"

//PICs (programmable interrupt controllers, master and slave)
public use object PIC_I8259 as PICa : PICa.DebugName=PICa.DebugName+"_A"
public use object PIC_I8259 as PICb : PICb.DebugName=PICb.DebugName+"_B"
SetPICs(PICa.Object,PICb.Object) 'init internal implementation

'-------------------------------- H/W Interface -------------------------------

//Set IRQ handler (master/slave mode)
public function SetIRQ(Index as integer, State as boolean) as boolean
 if Index<=7 then 'master interrupts
    Result=PICa.SetIRQ(Index,State) 
    if Index=2 then Result=PICb.SetIRQ(1,State) 'IRQ2 redirection to IRQ9
 elseif Index<=15 then 'slave interrupts
    Result=PICb.SetIRQ(Index-8,State)  'try to send IRQ to PIC-B
    if Result then PICa.SetIRQ(2,State) 'if success, inform PIC-A 
 else : result=false : end if
end direct SetIRQ

//Get IRQ handler (master/slave mode)
public function GetIRQ(Process as boolean,byref Address as dword) as integer
 Result=PICa.GetIRQ(false,Address) 'check master IRQ, if exists
 if Result=PICa.IRQ0Index+2 then 'this is slave interrupt (via IRQ2 as bridge)
    Result=PICb.GetIRQ(false,Address) 
    if Result>=0 then 
       'check and update IRQ2 request state by slave IRQs state
       if Process then
          PICa.GetIRQ(true,Address)
          PICb.GetIRQ(true,Address) 
          if (PICb.HasIRQs) and (not PICa.HasIRQ(2)) then PICa.SetIRQ(2,true)
       end if
    end if
 else if (Process) and (Result>=0) then 
    Result=PICa.GetIRQ(true,Address) 'check master IRQ, if exists
 end if : end if
end direct GetIRQ

