URL
https://opencores.org/ocsvn/openrisc/openrisc/trunk
Subversion Repositories openrisc
[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [hal/] [mips/] [upd985xx/] [v2_0/] [include/] [var_intr.h] - Rev 174
Compare with Previous | Blame | View Log
#ifndef CYGONCE_HAL_VAR_INTR_H #define CYGONCE_HAL_VAR_INTR_H //========================================================================== // // var_intr.h // // VR4300 Interrupt and clock support // //========================================================================== //####ECOSGPLCOPYRIGHTBEGIN#### // ------------------------------------------- // This file is part of eCos, the Embedded Configurable Operating System. // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. // // eCos is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free // Software Foundation; either version 2 or (at your option) any later version. // // eCos is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License // for more details. // // You should have received a copy of the GNU General Public License along // with eCos; if not, write to the Free Software Foundation, Inc., // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. // // As a special exception, if other files instantiate templates or use macros // or inline functions from this file, or you compile this file and link it // with other works to produce a work based on this file, this file does not // by itself cause the resulting work to be covered by the GNU General Public // License. However the source code for this file must still be made available // in accordance with section (3) of the GNU General Public License. // // This exception does not invalidate any other reasons why a work based on // this file might be covered by the GNU General Public License. // // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. // at http://sources.redhat.com/ecos/ecos-license/ // ------------------------------------------- //####ECOSGPLCOPYRIGHTEND#### //========================================================================== //#####DESCRIPTIONBEGIN#### // // Author(s): hmt, nickg // Contributors: nickg, jskov, // gthomas, jlarmour // Date: 2001-05-24 // Purpose: uPD985xx Interrupt support // Description: The macros defined here provide the HAL APIs for handling // interrupts and the clock for variants of the NEC uPD985xx // architecture. // // Usage: // #include <cyg/hal/var_intr.h> // ... // // //####DESCRIPTIONEND#### // //========================================================================== #include <cyg/hal/var_arch.h> #include <cyg/hal/plf_intr.h> //-------------------------------------------------------------------------- // Interrupt controller stuff. #ifndef CYGHWR_HAL_INTERRUPT_VECTORS_DEFINED // Interrupts dealt with via the status and cause registers // must be numbered in bit order: #define CYGNUM_HAL_INTERRUPT_STATUS_CAUSE_LOW (0) // The first two are the "software interrupts" - you just set a bit. #define CYGNUM_HAL_INTERRUPT_SOFT_ZERO (0) #define CYGNUM_HAL_INTERRUPT_SOFT_ONE (1) #define CYGNUM_HAL_INTERRUPT_FREE_TWO (2) #define CYGNUM_HAL_INTERRUPT_USB (3) #define CYGNUM_HAL_INTERRUPT_ETHER (4) #define CYGNUM_HAL_INTERRUPT_FREE_FIVE (5) #define CYGNUM_HAL_INTERRUPT_SYSCTL (6) #define CYGNUM_HAL_INTERRUPT_COMPARE (7) // Number 6 "SYSCTL" is all external sources in the system controller and // will normally be decoded into one of 8-12 instead. If you use number 6 // directly, then this will disable *all* system controller sources. // Startup code will ensure number 6 is unmasked by default, and it will // have an arbitration routine installed to call all of the subsequent // interrupts from the S_ISR register. This has to be an external routine // because the S_ISR register is read-clear, and the interrupt sources are // edge-triggered so they do not re-assert themselves - so we must address // multiple sources per actual interrupt, in a loop. #define CYGNUM_HAL_INTERRUPT_SYSCTL_LOW (8) #define CYGNUM_HAL_INTERRUPT_SYSCTL_HI (12) #define CYGNUM_HAL_INTERRUPT_TM0 (8) // TIMER CH0 interrupt. #define CYGNUM_HAL_INTERRUPT_TM1 (9) // TIMER CH1 interrupt. #define CYGNUM_HAL_INTERRUPT_UART (10) // UART interrupt. #define CYGNUM_HAL_INTERRUPT_EXT (11) // External Interrupt. #define CYGNUM_HAL_INTERRUPT_WU (12) // Wakeup Interrupt. #define CYGHWR_HAL_GDB_PORT_VECTOR CYGNUM_HAL_INTERRUPT_UART // Min/Max ISR numbers and how many there are #define CYGNUM_HAL_ISR_MIN 0 #define CYGNUM_HAL_ISR_MAX 12 #define CYGNUM_HAL_ISR_COUNT 13 // The vector used by the Real time clock. The default here is to use // interrupt 5, which is connected to the counter/comparator registers // in many MIPS variants. #ifndef CYGNUM_HAL_INTERRUPT_RTC #define CYGNUM_HAL_INTERRUPT_RTC CYGNUM_HAL_INTERRUPT_COMPARE #endif #define CYGHWR_HAL_INTERRUPT_VECTORS_DEFINED #endif // CYGHWR_HAL_INTERRUPT_VECTORS_DEFINED #ifndef __ASSEMBLER__ // ------------------------------------------------------------------------ // This is placed in memory at a fixed location because we must share it // with RedBoot, along with the VSR table and Virtual Vector table. // It has to be an array to get the correct code generation to access it // over all that distance. externC volatile cyg_uint32 hal_interrupt_sr_mask_shadow_base[]; #define hal_interrupt_sr_mask_shadow (hal_interrupt_sr_mask_shadow_base[0]) // We have to have local versions of these to preserve the mask bits in the // SR correctly when an interrupt occurs within one of these code sequences // which are doing a read-modify-write to the main interrupt bit of the SR. // Disable, it doesn't matter what the SR IM bits are - but it is possible // for control to return with interrupts enabled if a context switch occurs // away from the thread that disabled interrupts. Therefore we also make // sure the contents of the SR match the shadow variable at the end. #define HAL_DISABLE_INTERRUPTS(_old_) \ CYG_MACRO_START \ register int _tmp; \ asm volatile ( \ "mfc0 $8,$12; nop;" \ "move %0,$8;" \ "and $8,$8,0xfffffffe;" \ "mtc0 $8,$12;" \ "nop; nop; nop;" \ : "=r"(_tmp) \ : \ : "$8" \ ); \ /* interrupts disabled so can now inject the correct IM bits */ \ (_old_) = _tmp & 1; \ _tmp &= 0xffff00fe; \ _tmp |= (hal_interrupt_sr_mask_shadow & 0xff00); \ asm volatile ( \ "mtc0 %0,$12;" \ "nop; nop; nop;" \ : \ : "r"(_tmp) \ ); \ CYG_MACRO_END // Enable and restore, we must pick up hal_interrupt_sr_mask_shadow because // it contains the truth. This is also for the convenience of the // mask/unmask macros below. #define HAL_ENABLE_INTERRUPTS() HAL_RESTORE_INTERRUPTS(1) #define HAL_RESTORE_INTERRUPTS(_old_) \ CYG_MACRO_START \ asm volatile ( \ "mfc0 $8,$12; nop;" \ "or $8,$8,%0;" /* inject IE bit */ \ "and $8,$8,0xffff00ff;" /* clear IM bits */ \ "or $8,$8,%1;" /* insert true IM */ \ "mtc0 $8,$12;" \ "nop; nop; nop;" \ : \ : "r"((_old_) & 1),"r"(hal_interrupt_sr_mask_shadow & 0xff00) \ : "$8" \ ); \ CYG_MACRO_END #define HAL_QUERY_INTERRUPTS( _state_ ) \ CYG_MACRO_START \ asm volatile ( \ "mfc0 %0,$12; nop;" \ "and %0,%0,0x1;" \ : "=r"(_state_) \ ); \ CYG_MACRO_END #define CYGHWR_HAL_INTERRUPT_ENABLE_DISABLE_RESTORE_DEFINED // ------------------------------------------------------------------------ // For the bits which are in the SR, we only need to diddle the shadow // variable; restore interrupts will pick that up at the end of the macro. // Neat, huh. #ifndef CYGOPT_HAL_MIPS_UPD985XX_HARDWARE_BUGS_S2 // Vanilla versions here: trick versions with the workaround follow: #define HAL_INTERRUPT_MASK( _vector_ ) \ CYG_MACRO_START \ register int _intstate; \ register int _shift; \ HAL_DISABLE_INTERRUPTS( _intstate ); \ if ( CYGNUM_HAL_INTERRUPT_SYSCTL_LOW > (_vector_) ) { \ /* mask starts at bit 8 */ \ _shift = 8 + (_vector_) - CYGNUM_HAL_INTERRUPT_STATUS_CAUSE_LOW; \ hal_interrupt_sr_mask_shadow &=~(1 << _shift); \ } \ else { \ _shift = (_vector_) - CYGNUM_HAL_INTERRUPT_SYSCTL_LOW; \ *S_IMR &=~(1 << _shift); \ } \ HAL_RESTORE_INTERRUPTS( _intstate ); \ CYG_MACRO_END #define HAL_INTERRUPT_UNMASK( _vector_ ) \ CYG_MACRO_START \ register int _intstate; \ register int _shift; \ HAL_DISABLE_INTERRUPTS( _intstate ); \ if ( CYGNUM_HAL_INTERRUPT_SYSCTL_LOW > (_vector_) ) { \ /* mask starts at bit 8 */ \ _shift = 8 + (_vector_) - CYGNUM_HAL_INTERRUPT_STATUS_CAUSE_LOW; \ hal_interrupt_sr_mask_shadow |= (1 << _shift); \ } \ else { \ _shift = (_vector_) - CYGNUM_HAL_INTERRUPT_SYSCTL_LOW; \ *S_IMR |= (1 << _shift); \ } \ HAL_RESTORE_INTERRUPTS( _intstate ); \ CYG_MACRO_END #define HAL_INTERRUPT_ACKNOWLEDGE( _vector_ ) \ CYG_MACRO_START \ register int _intstate; \ HAL_DISABLE_INTERRUPTS( _intstate ); \ /* Default clears the bit in the cause register. But VR4120 doc */ \ /* says this is a NOP so we ignore low numbered sources except the */ \ /* software interrupt bits. */ \ if ( CYGNUM_HAL_INTERRUPT_SYSCTL_LOW <= (_vector_) || \ CYGNUM_HAL_INTERRUPT_SYSCTL == (_vector_) ) { \ register int i; \ i = *S_ISR; /* This is read-clear! */ \ } \ else if ( CYGNUM_HAL_INTERRUPT_SOFT_ZERO == (_vector_) || \ CYGNUM_HAL_INTERRUPT_SOFT_ONE == (_vector_) ) { \ /* These two are acknowledged by writing the bit to zero in */ \ /* the cause register. NB not the status register! */ \ asm volatile ( \ "mfc0 $3,$13\n" \ "la $2,0x00000100\n" \ "sllv $2,$2,%0\n" \ "andi $2,$2,0x0300\n" \ "nor $2,$2,$0\n" \ "and $3,$3,$2\n" \ "mtc0 $3,$13\n" \ "nop; nop; nop\n" \ : \ : "r"((_vector_)-CYGNUM_HAL_INTERRUPT_STATUS_CAUSE_LOW) \ : "$2", "$3" \ ); \ } \ HAL_RESTORE_INTERRUPTS( _intstate ); \ CYG_MACRO_END #else // DEFINED: CYGOPT_HAL_MIPS_UPD985XX_HARDWARE_BUGS_S2 #ifdef __cplusplus extern "C" { #endif extern void cyg_hal_interrupt_unmask( int vec ); extern void cyg_hal_interrupt_mask( int vec ); extern void cyg_hal_interrupt_acknowledge( int vec ); #ifdef __cplusplus } /* extern "C" */ #endif #define HAL_INTERRUPT_MASK( _vector_ ) \ CYG_MACRO_START \ register int _intstate; \ register int _shift; \ HAL_DISABLE_INTERRUPTS( _intstate ); \ if ( CYGNUM_HAL_INTERRUPT_SYSCTL_LOW > (_vector_) ) { \ /* mask starts at bit 8 */ \ _shift = 8 + (_vector_) - CYGNUM_HAL_INTERRUPT_STATUS_CAUSE_LOW; \ hal_interrupt_sr_mask_shadow &=~(1 << _shift); \ } \ else { \ cyg_hal_interrupt_mask( (_vector_) ); \ } \ HAL_RESTORE_INTERRUPTS( _intstate ); \ CYG_MACRO_END #define HAL_INTERRUPT_UNMASK( _vector_ ) \ CYG_MACRO_START \ register int _intstate; \ register int _shift; \ HAL_DISABLE_INTERRUPTS( _intstate ); \ if ( CYGNUM_HAL_INTERRUPT_SYSCTL_LOW > (_vector_) ) { \ /* mask starts at bit 8 */ \ _shift = 8 + (_vector_) - CYGNUM_HAL_INTERRUPT_STATUS_CAUSE_LOW; \ hal_interrupt_sr_mask_shadow |= (1 << _shift); \ } \ else { \ cyg_hal_interrupt_unmask( (_vector_) ); \ } \ HAL_RESTORE_INTERRUPTS( _intstate ); \ CYG_MACRO_END #define HAL_INTERRUPT_ACKNOWLEDGE( _vector_ ) \ CYG_MACRO_START \ register int _intstate; \ HAL_DISABLE_INTERRUPTS( _intstate ); \ /* Default clears the bit in the cause register. But VR4120 doc */ \ /* says this is a NOP so we ignore low numbered sources except the */ \ /* software interrupt bits. */ \ if ( CYGNUM_HAL_INTERRUPT_SYSCTL_LOW <= (_vector_) || \ CYGNUM_HAL_INTERRUPT_SYSCTL == (_vector_) ) { \ cyg_hal_interrupt_acknowledge( (_vector_) ); \ } \ else if ( CYGNUM_HAL_INTERRUPT_SOFT_ZERO == (_vector_) || \ CYGNUM_HAL_INTERRUPT_SOFT_ONE == (_vector_) ) { \ /* These two are acknowledged by writing the bit to zero in */ \ /* the cause register. NB not the status register! */ \ asm volatile ( \ "mfc0 $3,$13\n" \ "la $2,0x00000100\n" \ "sllv $2,$2,%0\n" \ "andi $2,$2,0x0300\n" \ "nor $2,$2,$0\n" \ "and $3,$3,$2\n" \ "mtc0 $3,$13\n" \ "nop; nop; nop\n" \ : \ : "r"((_vector_)-CYGNUM_HAL_INTERRUPT_STATUS_CAUSE_LOW) \ : "$2", "$3" \ ); \ } \ HAL_RESTORE_INTERRUPTS( _intstate ); \ CYG_MACRO_END #endif // CYGOPT_HAL_MIPS_UPD985XX_HARDWARE_BUGS_S2 #define HAL_INTERRUPT_CONFIGURE( _vector_, _level_, _up_ ) #define HAL_INTERRUPT_SET_LEVEL( _vector_, _level_ ) #define CYGHWR_HAL_INTERRUPT_CONTROLLER_ACCESS_DEFINED //-------------------------------------------------------------------------- // Useful for debugging... #define HAL_READ_INTR_REGS( _status, _cause ) \ { \ asm volatile ( \ "mfc0 %0,$12; nop;" \ : "=r"(_status) \ ); \ asm volatile ( \ "mfc0 %0,$13; nop;" \ : "=r"(_cause) \ ); \ } //-------------------------------------------------------------------------- #endif // ! __ASSEMBLER__ #endif // ifndef CYGONCE_HAL_VAR_INTR_H // End of var_intr.h