// Timebase interrupt can be caused by match on either reference A // or B. // Note: If only one interrupt source is assigned per vector, and only // reference interrupt A or B is used, this ISR is not // necessary. Attach the timerbase reference A or B ISR directly to // the LVLx vector instead. externC cyg_uint32 hal_arbitration_isr_tb (CYG_ADDRWORD vector, CYG_ADDRWORD data) { cyg_uint32 isr_ret; cyg_uint16 tbscr; HAL_READ_UINT16 (CYGARC_REG_IMM_TBSCR, tbscr); if (tbscr & CYGARC_REG_IMM_TBSCR_REFA) { isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_SIU_TB_A); #ifdef CYGIMP_HAL_COMMON_INTERRUPTS_CHAIN if (isr_ret & CYG_ISR_HANDLED) #endif return isr_ret; } if (tbscr & CYGARC_REG_IMM_TBSCR_REFB) { isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_SIU_TB_B); #ifdef CYGIMP_HAL_COMMON_INTERRUPTS_CHAIN if (isr_ret & CYG_ISR_HANDLED) #endif return isr_ret; } return 0; }
// Real time clock interrupts can be caused by the alarm or // once-per-second. // Note: If only one interrupt source is assigned per vector, and only // the alarm or once-per-second interrupt is used, this ISR is not // necessary. Attach the alarm or once-per-second ISR directly to the // LVLx vector instead. externC cyg_uint32 hal_arbitration_isr_rtc (CYG_ADDRWORD vector, CYG_ADDRWORD data) { cyg_uint32 isr_ret; cyg_uint16 rtcsc; HAL_READ_UINT16 (CYGARC_REG_IMM_RTCSC, rtcsc); if (rtcsc & CYGARC_REG_IMM_RTCSC_SEC) { isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_SIU_RTC_SEC); #ifdef CYGIMP_HAL_COMMON_INTERRUPTS_CHAIN if (isr_ret & CYG_ISR_HANDLED) #endif return isr_ret; } if (rtcsc & CYGARC_REG_IMM_RTCSC_ALR) { isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_SIU_RTC_ALR); #ifdef CYGIMP_HAL_COMMON_INTERRUPTS_CHAIN if (isr_ret & CYG_ISR_HANDLED) #endif return isr_ret; } return 0; }
// Default arbitration ISR for serial interrupts. Although such arbitration // belongs in the serial device driver, we require this default implementation // for CTRL-C interrupts to be delivered correctly to any running ROM monitor. // A device driver that uses more than just receive interrupts may of course // provide its own arbiter. externC cyg_uint32 hal_arbitration_isr_sci(CYG_ADDRWORD vector, CYG_ADDRWORD data) { cyg_uint32 isr_ret; cyg_uint16 scc_sr; cyg_uint16 scc_cr; // Try SCI0 HAL_READ_UINT16(CYGARC_REG_IMM_SC1SR, scc_sr); HAL_READ_UINT16(CYGARC_REG_IMM_SCC1R1, scc_cr); if ((scc_sr & CYGARC_REG_IMM_SCxSR_RDRF) && (scc_cr & CYGARC_REG_IMM_SCCxR1_RIE)) { isr_ret = hal_call_isr(CYGNUM_HAL_INTERRUPT_IMB3_SCI0_RX); #ifdef CYGIMP_HAL_COMMON_INTERRUPTS_CHAIN if (isr_ret & CYG_ISR_HANDLED) #endif return isr_ret; } HAL_READ_UINT16(CYGARC_REG_IMM_SC2SR, scc_sr); HAL_READ_UINT16(CYGARC_REG_IMM_SCC2R1, scc_cr); if ((scc_sr & CYGARC_REG_IMM_SCxSR_RDRF) && (scc_cr & CYGARC_REG_IMM_SCCxR1_RIE)) { isr_ret = hal_call_isr(CYGNUM_HAL_INTERRUPT_IMB3_SCI1_RX); #ifdef CYGIMP_HAL_COMMON_INTERRUPTS_CHAIN if (isr_ret & CYG_ISR_HANDLED) #endif return isr_ret; } return 0; }
//-------------------------------------------------------------------------- // PCI interrupt decoding static cyg_uint32 cyg_hal_plf_pci_arbiter(CYG_ADDRWORD vector, CYG_ADDRWORD data) { cyg_uint32 isr_ret, int_sts; HAL_READ_UINT32(CYGARC_REG_SD0001_INT_STS1, int_sts); if (int_sts & CYGARC_REG_SD0001_INT_INTA) { isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_PCIA); #ifdef CYGIMP_HAL_COMMON_INTERRUPTS_CHAIN if (isr_ret & CYG_ISR_HANDLED) #endif return isr_ret; } if (int_sts & CYGARC_REG_SD0001_INT_INTB) { isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_PCIB); #ifdef CYGIMP_HAL_COMMON_INTERRUPTS_CHAIN if (isr_ret & CYG_ISR_HANDLED) #endif return isr_ret; } if (int_sts & CYGARC_REG_SD0001_INT_INTC) { isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_PCIC); #ifdef CYGIMP_HAL_COMMON_INTERRUPTS_CHAIN if (isr_ret & CYG_ISR_HANDLED) #endif return isr_ret; } if (int_sts & CYGARC_REG_SD0001_INT_INTD) { isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_PCID); #ifdef CYGIMP_HAL_COMMON_INTERRUPTS_CHAIN if (isr_ret & CYG_ISR_HANDLED) #endif return isr_ret; } return 0; }
// Periodic interrupt. // Note: If only one interrupt source is assigned per vector, this ISR // is not necessary. Attach the periodic interrupt ISR directly to the // LVLx vector instead. externC cyg_uint32 hal_arbitration_isr_pit (CYG_ADDRWORD vector, CYG_ADDRWORD data) { cyg_uint32 isr_ret; cyg_uint16 piscr; HAL_READ_UINT16 (CYGARC_REG_IMM_PISCR, piscr); if (piscr & CYGARC_REG_IMM_PISCR_PS) { isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_SIU_PIT); #ifdef CYGIMP_HAL_COMMON_INTERRUPTS_CHAIN if (isr_ret & CYG_ISR_HANDLED) #endif return isr_ret; } return 0; }
// Communication Processor Module interrupt can be caused by any of // the CPM sources. externC cyg_uint32 hal_arbitration_isr_cpm (CYG_ADDRWORD vector, CYG_ADDRWORD data) { cyg_uint32 isr_ret; cyg_uint16 civr; HAL_WRITE_UINT16 (CYGARC_REG_IMM_CIVR, CYGARC_REG_IMM_CIVR_IACK); HAL_READ_UINT16 (CYGARC_REG_IMM_CIVR, civr); civr >>= CYGARC_REG_IMM_CIVR_VECTOR_SHIFT; if (civr) { isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_CPM_LAST - civr); #ifdef CYGIMP_HAL_COMMON_INTERRUPTS_CHAIN if (isr_ret & CYG_ISR_HANDLED) #endif return isr_ret; } return 0; }
externC cyg_uint32 hal_extended_isr(CYG_ADDRWORD vector, CYG_ADDRWORD data) { cyg_uint32 isrRet; cyg_uint32 pendingIsr; cyg_uint32 isrNum; HAL_READ_UINT32 (INTR_STATUS_PTR, pendingIsr); for (isrNum=0; isrNum <=31; isrNum) if ( (1 << isrNum) & pendingIsr) break; if (pendingIsr) { isrRet = hal_call_isr (CYGNUM_LAST_IDT_INTERRUPT + isrNum); if (isrRet & CYG_ISR_HANDLED) return isrRet; } return 0; }
// The arbitration isr. // I think this is the best place to implement it. The device driver is the only place // in the code where the knowledge is present about how the hardware is used static cyg_uint32 hal_arbitration_isr_qsci(CYG_ADDRWORD a_vector, CYG_ADDRWORD a_data) { cyg_uint16 status; cyg_uint16 control; #ifdef CYGPKG_IO_SERIAL_POWERPC_EC555_SERIAL_A // Do not waist time on unused hardware HAL_READ_UINT16(CYGARC_REG_IMM_SC1SR, status); HAL_READ_UINT16(CYGARC_REG_IMM_SCC1R1, control); if((status & CYGARC_REG_IMM_SCxSR_TDRE) && (control & CYGARC_REG_IMM_SCCxR1_TIE)) return hal_call_isr(CYGNUM_HAL_INTERRUPT_IMB3_SCI0_TX); // Don't waist time on unused interrupts // if((status & CYGARC_REG_IMM_SCxSR_TC) && (control & CYGARC_REG_IMM_SCCxR1_TCIE)) // return hal_call_isr(CYGNUM_HAL_INTERRUPT_IMB3_SCI0_TXC); if((status & CYGARC_REG_IMM_SCxSR_RDRF) && (control & CYGARC_REG_IMM_SCCxR1_RIE)) return hal_call_isr(CYGNUM_HAL_INTERRUPT_IMB3_SCI0_RX); // Don't waist time on unused interrupts // if((status & CYGARC_REG_IMM_SCxSR_IDLE) && (control & CYGARC_REG_IMM_SCCxR1_ILIE)) // return hal_call_isr(CYGNUM_HAL_INTERRUPT_IMB3_SCI0_IDLE); #endif #ifdef CYGPKG_IO_SERIAL_POWERPC_EC555_SERIAL_B // Do not waist time on unused hardware HAL_READ_UINT16(CYGARC_REG_IMM_SC2SR, status); HAL_READ_UINT16(CYGARC_REG_IMM_SCC2R1, control); if((status & CYGARC_REG_IMM_SCxSR_TDRE) && (control & CYGARC_REG_IMM_SCCxR1_TIE)) return hal_call_isr(CYGNUM_HAL_INTERRUPT_IMB3_SCI1_TX); // Don't waist time on unused interrupts // if((status & CYGARC_REG_IMM_SCxSR_TC) && (control & CYGARC_REG_IMM_SCCxR1_TCIE)) // return hal_call_isr(CYGNUM_HAL_INTERRUPT_IMB3_SCI1_TXC); if((status & CYGARC_REG_IMM_SCxSR_RDRF) && (control & CYGARC_REG_IMM_SCCxR1_RIE)) return hal_call_isr(CYGNUM_HAL_INTERRUPT_IMB3_SCI1_RX); // Don't waist time on unused interrupts // if((status & CYGARC_REG_IMM_SCxSR_IDLE) && (control & CYGARC_REG_IMM_SCCxR1_ILIE)) // return hal_call_isr(CYGNUM_HAL_INTERRUPT_IMB3_SCI1_IDLE); #if 0 // The driver doesn't use the queue operation of the hardware (It would need different code for serial 1 and 2 // since oly one port supports queue mode). So the following is not needed. // Leave it there. It is easyer for later implementations to remove the comments than finding // out how the hardware works again. HAL_READ_UINT16(CYGARC_REG_IMM_QSCI1SR, status); HAL_READ_UINT16(CYGARC_REG_IMM_QSCI1CR, control); if((status & CYGARC_REG_IMM_QSCI1SR_QTHF) && (control & CYGARC_REG_IMM_QSCI1CR_QTHFI)) return hal_call_isr(CYGNUM_HAL_INTERRUPT_IMB3_SCI1_RXQTHF); if((status & CYGARC_REG_IMM_QSCI1SR_QBHF) && (control & CYGARC_REG_IMM_QSCI1CR_QBHFI)) return hal_call_isr(CYGNUM_HAL_INTERRUPT_IMB3_SCI1_RXQBHF); if((status & CYGARC_REG_IMM_QSCI1SR_QTHE) && (control & CYGARC_REG_IMM_QSCI1CR_QTHEI)) return hal_call_isr(CYGNUM_HAL_INTERRUPT_IMB3_SCI1_TXQTHE); if((status & CYGARC_REG_IMM_QSCI1SR_QBHE) && (control & CYGARC_REG_IMM_QSCI1CR_QBHEI)) return hal_call_isr(CYGNUM_HAL_INTERRUPT_IMB3_SCI1_TXQBHE); cyg_uint16 status; cyg_uint16 control; HAL_READ_UINT16(CYGARC_REG_IMM_SPSR, status); HAL_READ_UINT16(CYGARC_REG_IMM_SPCR2, control); if((status & CYGARC_REG_IMM_SPSR_SPIF) && (control & CYGARC_REG_IMM_SPCR2_SPIFIE)) return hal_call_isr(CYGNUM_HAL_INTERRUPT_IMB3_SPI_FI); HAL_READ_UINT16(CYGARC_REG_IMM_SPCR3, control); if((status & CYGARC_REG_IMM_SPSR_MODF) && (control & CYGARC_REG_IMM_SPCR3_HMIE)) return hal_call_isr(CYGNUM_HAL_INTERRUPT_IMB3_SPI_MODF); if((status & CYGARC_REG_IMM_SPSR_HALTA) && (control & CYGARC_REG_IMM_SPCR3_HMIE)) return hal_call_isr(CYGNUM_HAL_INTERRUPT_IMB3_SPI_HALTA); #endif #endif return 0; }