#include "holly_intc.h" #include "sb.h" #include "hw/sh4/sh4_interrupts.h" /* ASIC Interrupt controller part of the holly block on dc */ //asic_RLXXPending: Update the intc flags for pending interrupts static void asic_RL6Pending() { bool t1 = (SB_ISTNRM & SB_IML6NRM) != 0; bool t2 = (SB_ISTERR & SB_IML6ERR) != 0; bool t3 = (SB_ISTEXT & SB_IML6EXT) != 0; bool t4 = (SB_ISTNRM1 & SB_IML6NRM) != 0; InterruptPend(sh4_IRL_9,t1 | t2 | t3 | t4); } static void asic_RL4Pending() { bool t1 = (SB_ISTNRM & SB_IML4NRM) != 0; bool t2 = (SB_ISTERR & SB_IML4ERR) != 0; bool t3 = (SB_ISTEXT & SB_IML4EXT) != 0; bool t4 = (SB_ISTNRM1 & SB_IML4NRM) != 0; InterruptPend(sh4_IRL_11, t1 | t2 | t3 | t4); } static void asic_RL2Pending() { bool t1 = (SB_ISTNRM & SB_IML2NRM) != 0; bool t2 = (SB_ISTERR & SB_IML2ERR) != 0; bool t3 = (SB_ISTEXT & SB_IML2EXT) != 0; bool t4 = (SB_ISTNRM1 & SB_IML2NRM) != 0; InterruptPend(sh4_IRL_13, t1 | t2 | t3 | t4); } void asic_RaiseInterrupt(HollyInterruptID inter) { u8 type = inter >> 8; u32 mask = 1 << (u8)inter; switch(type) { case 0: SB_ISTNRM |= mask; break; case 1: SB_ISTEXT |= mask; break; case 2: SB_ISTERR |= mask; break; } asic_RL2Pending(); asic_RL4Pending(); asic_RL6Pending(); } void asic_RaiseInterruptBothCLX(HollyInterruptID inter) { u8 type = inter >> 8; u32 mask = 1 << (u8)inter; switch(type) { case 0: SB_ISTNRM1 |= mask; SB_ISTNRM |= mask; break; case 1: SB_ISTEXT |= mask; break; case 2: SB_ISTERR |= mask; break; } asic_RL2Pending(); asic_RL4Pending(); asic_RL6Pending(); } template static u32 Read_SB_ISTNRM(u32 addr) { /* Note that the two highest bits indicate * the OR'ed result of all the bits in * SB_ISTEXT and SB_ISTERR, respectively, * and writes to these two bits are ignored. */ u32 tmp = (Naomi2 && (addr & 0x02000000) != 0 ? SB_ISTNRM1 : SB_ISTNRM) & 0x3FFFFFFF; if (SB_ISTEXT) tmp|=0x40000000; if (SB_ISTERR) tmp|=0x80000000; return tmp; } template static void Write_SB_ISTNRM(u32 addr, u32 data) { /* writing a 1 clears the interrupt */ if (Naomi2 && (addr & 0x02000000) != 0) SB_ISTNRM1 &= ~data; else SB_ISTNRM &= ~data; asic_RL2Pending(); asic_RL4Pending(); asic_RL6Pending(); } void asic_CancelInterrupt(HollyInterruptID inter) { u8 type = inter >> 8; u32 mask = ~(1 << (u8)inter); switch (type) { case 0: SB_ISTNRM &= mask; break; case 1: SB_ISTEXT &= mask; break; case 2: SB_ISTERR &= mask; break; } asic_RL2Pending(); asic_RL4Pending(); asic_RL6Pending(); } static void Write_SB_ISTEXT(u32 addr, u32 data) { //nothing happens -- asic_CancelInterrupt is used instead } static void Write_SB_ISTERR(u32 addr, u32 data) { SB_ISTERR &= ~data; asic_RL2Pending(); asic_RL4Pending(); asic_RL6Pending(); } template static void Write_SB_IML6NRM(u32 addr, u32 data) { if (Naomi2 && (addr & 0x2000000) != 0) // Ignore CLXB settings return; SB_IML6NRM = data; asic_RL6Pending(); } template static void Write_SB_IML4NRM(u32 addr, u32 data) { if (Naomi2 && (addr & 0x2000000) != 0) // Ignore CLXB settings return; SB_IML4NRM = data; asic_RL4Pending(); } template static void Write_SB_IML2NRM(u32 addr, u32 data) { if (Naomi2 && (addr & 0x2000000) != 0) // Ignore CLXB settings return; SB_IML2NRM = data; asic_RL2Pending(); } template static void Write_SB_IML6EXT(u32 addr, u32 data) { if (Naomi2 && (addr & 0x2000000) != 0) // Ignore CLXB settings return; SB_IML6EXT = data; asic_RL6Pending(); } template static void Write_SB_IML4EXT(u32 addr, u32 data) { if (Naomi2 && (addr & 0x2000000) != 0) // Ignore CLXB settings return; SB_IML4EXT = data; asic_RL4Pending(); } template static void Write_SB_IML2EXT(u32 addr, u32 data) { if (Naomi2 && (addr & 0x2000000) != 0) // Ignore CLXB settings return; SB_IML2EXT = data; asic_RL2Pending(); } template static void Write_SB_IML6ERR(u32 addr, u32 data) { if (Naomi2 && (addr & 0x2000000) != 0) // Ignore CLXB settings return; SB_IML6ERR = data; asic_RL6Pending(); } template static void Write_SB_IML4ERR(u32 addr, u32 data) { if (Naomi2 && (addr & 0x2000000) != 0) // Ignore CLXB settings return; SB_IML4ERR = data; asic_RL4Pending(); } template static void Write_SB_IML2ERR(u32 addr, u32 data) { if (Naomi2 && (addr & 0x2000000) != 0) // Ignore CLXB settings return; SB_IML2ERR = data; asic_RL2Pending(); } void asic_reg_Init() { } void asic_reg_Term() { } //Reset -> Reset - Initialise to default values void asic_reg_Reset(bool hard) { if (hard) { sb_rio_register(SB_ISTEXT_addr, RIO_WF, 0, &Write_SB_ISTEXT); sb_rio_register(SB_ISTERR_addr, RIO_WF, 0, &Write_SB_ISTERR); if (settings.platform.isNaomi2()) { sb_rio_register(SB_ISTNRM_addr, RIO_FUNC, &Read_SB_ISTNRM, &Write_SB_ISTNRM); //NRM //6 sb_rio_register(SB_IML6NRM_addr, RIO_WF, 0, &Write_SB_IML6NRM); //4 sb_rio_register(SB_IML4NRM_addr, RIO_WF, 0, &Write_SB_IML4NRM); //2 sb_rio_register(SB_IML2NRM_addr, RIO_WF, 0, &Write_SB_IML2NRM); //EXT //6 sb_rio_register(SB_IML6EXT_addr, RIO_WF, 0, &Write_SB_IML6EXT); //4 sb_rio_register(SB_IML4EXT_addr, RIO_WF, 0, &Write_SB_IML4EXT); //2 sb_rio_register(SB_IML2EXT_addr, RIO_WF, 0, &Write_SB_IML2EXT); //ERR //6 sb_rio_register(SB_IML6ERR_addr, RIO_WF, 0, &Write_SB_IML6ERR); //4 sb_rio_register(SB_IML4ERR_addr, RIO_WF, 0, &Write_SB_IML4ERR); //2 sb_rio_register(SB_IML2ERR_addr, RIO_WF, 0, &Write_SB_IML2ERR); } else { sb_rio_register(SB_ISTNRM_addr, RIO_FUNC, &Read_SB_ISTNRM, &Write_SB_ISTNRM); //NRM //6 sb_rio_register(SB_IML6NRM_addr, RIO_WF, 0, &Write_SB_IML6NRM); //4 sb_rio_register(SB_IML4NRM_addr, RIO_WF, 0, &Write_SB_IML4NRM); //2 sb_rio_register(SB_IML2NRM_addr, RIO_WF, 0, &Write_SB_IML2NRM); //EXT //6 sb_rio_register(SB_IML6EXT_addr, RIO_WF, 0, &Write_SB_IML6EXT); //4 sb_rio_register(SB_IML4EXT_addr, RIO_WF, 0, &Write_SB_IML4EXT); //2 sb_rio_register(SB_IML2EXT_addr, RIO_WF, 0, &Write_SB_IML2EXT); //ERR //6 sb_rio_register(SB_IML6ERR_addr, RIO_WF, 0, &Write_SB_IML6ERR); //4 sb_rio_register(SB_IML4ERR_addr, RIO_WF, 0, &Write_SB_IML4ERR); //2 sb_rio_register(SB_IML2ERR_addr, RIO_WF, 0, &Write_SB_IML2ERR); } } }