Ignore:
Timestamp:
04/22/96 16:30:02 (28 years ago)
Author:
Joel Sherrill <joel.sherrill@…>
Branches:
4.10, 4.11, 4.8, 4.9, 5, master
Children:
f581163a
Parents:
767a6c6
Message:

updartes from Tony Bennett

File:
1 edited

Legend:

Unmodified
Added
Removed
  • c/src/exec/score/cpu/hppa1.1/cpu.c

    r767a6c6 rd0b7c4e6  
    2020#include <rtems/system.h>
    2121#include <rtems/score/isr.h>
     22void hppa_cpu_halt(unsigned32 the_error);
    2223
    23 void hppa_external_interrupt_initialize(void);
    24 void hppa_external_interrupt_enable(unsigned32);
    25 void hppa_external_interrupt_disable(unsigned32);
    26 void hppa_external_interrupt(unsigned32, CPU_Interrupt_frame *);
    27 void hppa_cpu_halt(unsigned32);
     24
     25/*PAGE
     26 *
     27 *  _CPU_ISR_install_raw_handler
     28 */
     29 
     30void _CPU_ISR_install_raw_handler(
     31  unsigned32  vector,
     32  proc_ptr    new_handler,
     33  proc_ptr   *old_handler
     34)
     35{
     36  /*
     37   *  This is unsupported.  For HPPA this function is handled by BSP
     38   */
     39
     40  _CPU_Fatal_halt( 0xdeaddead );
     41}
     42
     43
    2844
    2945/*
    30  * The first level interrupt handler for first 32 interrupts/traps.
    31  * Indexed by vector; generally each entry is _Generic_ISR_Handler.
    32  * Some TLB traps may have their own first level handler.
     46 * This is the default handler which is called if
     47 * _CPU_ISR_install_vector() has not been called for the
     48 * specified vector.  It simply forwards onto the spurious
     49 * handler defined in the cpu-table.
    3350 */
    3451
    35 extern void _Generic_ISR_Handler(void);
    36 unsigned32 HPPA_first_level_interrupt_handler[HPPA_INTERNAL_INTERRUPTS];
     52static ISR_Handler
     53hppa_interrupt_report_spurious(ISR_Vector_number vector,
     54                               void* rtems_isr_frame) /* HPPA extension */
     55{
     56
     57    /*
     58     * If the CPU table defines a spurious_handler, then
     59     * call it.  If the handler returns halt.
     60     */
     61    if ( _CPU_Table.spurious_handler )
     62        _CPU_Table.spurious_handler(vector, rtems_isr_frame);
     63   
     64    hppa_cpu_halt(vector);
     65}
     66
     67
     68/*PAGE
     69 *
     70 *  _CPU_ISR_Get_level
     71 */
     72 
     73unsigned32 _CPU_ISR_Get_level(void)
     74{
     75    int level;
     76    HPPA_ASM_SSM(0, level);     /* change no bits; just get copy */
     77    if (level & HPPA_PSW_I)
     78        return 0;
     79    return 1;
     80}
     81
     82/*PAGE
     83 *
     84 *  _CPU_ISR_install_vector
     85 *
     86 *  This kernel routine installs the RTEMS handler for the
     87 *  specified vector.  The handler is a C callable routine.
     88 *
     89 *  Input parameters:
     90 *    vector      - interrupt vector number
     91 *    old_handler - former ISR for this vector number
     92 *    new_handler - replacement ISR for this vector number
     93 *
     94 *  Output parameters:  NONE
     95 *
     96 */
     97
     98void _CPU_ISR_install_vector(
     99  unsigned32  vector,
     100  proc_ptr    new_handler,
     101  proc_ptr   *old_handler
     102)
     103{
     104    *old_handler = _ISR_Vector_table[vector];
     105
     106    _ISR_Vector_table[vector] = new_handler;
     107}
    37108
    38109/*  _CPU_Initialize
     
    52123{
    53124    register unsigned8  *fp_context;
    54     unsigned32 iva;
    55     unsigned32 iva_table;
    56125    int i;
    57 
    58     extern void IVA_Table(void);
     126    proc_ptr   old_handler;
    59127
    60128    /*
     
    74142
    75143    /*
    76      * Init the first level interrupt handlers
    77      */
    78 
    79     for (i=0; i <= HPPA_INTERNAL_INTERRUPTS; i++)
    80         HPPA_first_level_interrupt_handler[i] = (unsigned32) _Generic_ISR_Handler;
    81 
    82     /*
    83144     * Init the 2nd level interrupt handlers
    84145     */
    85146
    86     for (i=0; i <= CPU_INTERRUPT_NUMBER_OF_VECTORS; i++)
    87         _ISR_Vector_table[i] = (ISR_Handler_entry) hppa_cpu_halt;
    88 
    89     /*
    90      * Stabilize the interrupt stuff
    91      */
    92 
    93     (void) hppa_external_interrupt_initialize();
    94 
    95     /*
    96      * Set the IVA to point to physical address of the IVA_Table
    97      */
    98 
    99     iva_table = (unsigned32) IVA_Table;
    100 #if defined(hppa1_1)
    101     /*
    102      * HACK:  (from PA72000 TRM, page 4-19)
    103      * "The hardware TLB miss handler will never attempt to service
    104      *  a non-access TLB miss or a TLB protection violation.  It
    105      *  will only attempt to service TLB accesses that would cause
    106      *  Trap Numbers 6 (Instruction TLB miss) and 15 (Data TLB miss)."
    107      *
    108      * The LPA instruction is used to translate a virtual address to
    109      * a physical address, however, if the requested virtual address
    110      * is not currently resident in the TLB, the hardware TLB miss
    111      * handler will NOT insert it.  In this situation Trap Number
    112      * #17 is invoked (Non-access Data TLB miss fault).
    113      *
    114      * To work around this, a dummy data access is first performed
    115      * to the virtual address prior to the LPA.  The dummy access
    116      * causes the TLB entry to be inserted (if not already present)
    117      * and then the following LPA instruction will not generate
    118      * a non-access data TLB miss fault.
    119      *
    120      * It is unclear whether or not this behaves the same way for
    121      * the PA8000.
    122      *
    123      */
    124     iva = *(volatile unsigned32 *)iva_table;  /* dummy access */
    125 #endif
    126 
    127     HPPA_ASM_LPA(0, iva_table, iva);
    128     set_iva(iva);
     147    for (i=0; i < CPU_INTERRUPT_NUMBER_OF_VECTORS; i++)
     148        _CPU_ISR_install_vector(i,
     149                                hppa_interrupt_report_spurious,
     150                                &old_handler);
    129151
    130152    _CPU_Table = *cpu_table;
     153   
    131154}
    132155
    133 /*PAGE
    134  *
    135  *  _CPU_ISR_Get_level
    136  */
    137  
    138 unsigned32 _CPU_ISR_Get_level(void)
    139 {
    140     int level;
    141     HPPA_ASM_SSM(0, level);     /* change no bits; just get copy */
    142     if (level & HPPA_PSW_I)
    143         return 0;
    144     return 1;
    145 }
    146 
    147 /*PAGE
    148  *
    149  *  _CPU_ISR_install_raw_handler
    150  */
    151  
    152 void _CPU_ISR_install_raw_handler(
    153   unsigned32  vector,
    154   proc_ptr    new_handler,
    155   proc_ptr   *old_handler
    156 )
    157 {
    158   /*
    159    *  This is unsupported.
    160    */
    161 
    162   _CPU_Fatal_halt( 0xdeaddead );
    163 }
    164 
    165 /*PAGE
    166  *
    167  *  _CPU_ISR_install_vector
    168  *
    169  *  This kernel routine installs the RTEMS handler for the
    170  *  specified vector.
    171  *
    172  *  Input parameters:
    173  *    vector      - interrupt vector number
    174  *    old_handler - former ISR for this vector number
    175  *    new_handler - replacement ISR for this vector number
    176  *
    177  *  Output parameters:  NONE
    178  *
    179  */
    180 
    181 /*
    182  * HPPA has 8w for each vector instead of an address to jump to.
    183  * We put the actual ISR address in '_ISR_vector_table'.  This will
    184  * be pulled by the code in the vector.
    185  */
    186 
    187 void _CPU_ISR_install_vector(
    188   unsigned32  vector,
    189   proc_ptr    new_handler,
    190   proc_ptr   *old_handler
    191 )
    192 {
    193     *old_handler = _ISR_Vector_table[vector];
    194 
    195     _ISR_Vector_table[vector] = new_handler;
    196 
    197     if (vector >= HPPA_INTERRUPT_EXTERNAL_BASE)
    198     {
    199         unsigned32 external_vector;
    200 
    201         external_vector = vector - HPPA_INTERRUPT_EXTERNAL_BASE;
    202         if (new_handler)
    203             hppa_external_interrupt_enable(external_vector);
    204         else
    205             /* XXX this can never happen due to _ISR_Is_valid_user_handler */
    206             hppa_external_interrupt_disable(external_vector);
    207     }
    208 }
    209 
    210 
    211 /*
    212  * Support for external and spurious interrupts on HPPA
    213  *
    214  *  TODO:
    215  *    Count interrupts
    216  *    make sure interrupts disabled properly
    217  */
    218 
    219 #define DISMISS(mask)           set_eirr(mask)
    220 #define DISABLE(mask)           set_eiem(get_eiem() & ~(mask))
    221 #define ENABLE(mask)            set_eiem(get_eiem() | (mask))
    222 #define VECTOR_TO_MASK(v)       (1 << (31 - (v)))
    223 
    224 /*
    225  * Init the external interrupt scheme
    226  * called by bsp_start()
    227  */
    228 
    229 void
    230 hppa_external_interrupt_initialize(void)
    231 {
    232     proc_ptr ignore;
    233 
    234     /* mark them all unused */
    235     DISABLE(~0);
    236     DISMISS(~0);
    237 
    238     /* install the external interrupt handler */
    239     _CPU_ISR_install_vector(
    240         HPPA_INTERRUPT_EXTERNAL_INTERRUPT,
    241         (proc_ptr)hppa_external_interrupt, &ignore
    242 );
    243 }
    244 
    245 /*
    246  * Enable a specific external interrupt
    247  */
    248 
    249 void
    250 hppa_external_interrupt_enable(unsigned32 v)
    251 {
    252     unsigned32 isrlevel;
    253 
    254     _CPU_ISR_Disable(isrlevel);
    255     ENABLE(VECTOR_TO_MASK(v));
    256     _CPU_ISR_Enable(isrlevel);
    257 }
    258 
    259 /*
    260  * Does not clear or otherwise affect any pending requests
    261  */
    262 
    263 void
    264 hppa_external_interrupt_disable(unsigned32 v)
    265 {
    266     unsigned32 isrlevel;
    267 
    268     _CPU_ISR_Disable(isrlevel);
    269     DISABLE(VECTOR_TO_MASK(v));
    270     _CPU_ISR_Enable(isrlevel);
    271 }
    272 
    273 void
    274 hppa_external_interrupt_spurious_handler(unsigned32           vector,
    275                                          CPU_Interrupt_frame *iframe)
    276 {
    277 /* XXX should not be printing :)
    278     printf("spurious external interrupt: %d at pc 0x%x; disabling\n",
    279        vector, iframe->Interrupt.pcoqfront);
    280 */
    281 }
    282 
    283 void
    284 hppa_external_interrupt_report_spurious(unsigned32           spurious_mask,
    285                                         CPU_Interrupt_frame *iframe)
    286 {
    287     int v;
    288     for (v=0; v < HPPA_EXTERNAL_INTERRUPTS; v++)
    289         if (VECTOR_TO_MASK(v) & spurious_mask)
    290         {
    291             DISMISS(VECTOR_TO_MASK(v));
    292             DISABLE(VECTOR_TO_MASK(v));
    293             hppa_external_interrupt_spurious_handler(v, iframe);
    294         }
    295     DISMISS(spurious_mask);
    296 }
    297 
    298 
    299 /*
    300  * External interrupt handler.
    301  * This is installed as cpu interrupt handler for
    302  * HPPA_INTERRUPT_EXTERNAL_INTERRUPT. It vectors out to
    303  * specific external interrupt handlers.
    304  */
    305 
    306 void
    307 hppa_external_interrupt(unsigned32           vector,
    308                         CPU_Interrupt_frame *iframe)
    309 {
    310     unsigned32   mask;
    311     unsigned32  *vp, *max_vp;
    312     unsigned32   external_vector;
    313     unsigned32   global_vector;
    314     hppa_rtems_isr_entry handler;
    315 
    316     max_vp = &_CPU_Table.external_interrupt[_CPU_Table.external_interrupts];
    317     while ( (mask = (get_eirr() & get_eiem())) )
    318     {
    319         for (vp = _CPU_Table.external_interrupt; (vp < max_vp) && mask; vp++)
    320         {
    321             unsigned32 m;
    322 
    323             external_vector = *vp;
    324             global_vector = external_vector + HPPA_INTERRUPT_EXTERNAL_BASE;
    325             m = VECTOR_TO_MASK(external_vector);
    326             handler = (hppa_rtems_isr_entry) _ISR_Vector_table[global_vector];
    327             if ((m & mask) && handler)
    328             {
    329                 DISMISS(m);
    330                 mask &= ~m;
    331                 handler(global_vector, iframe);
    332             }
    333         }
    334 
    335         if (mask != 0) {
    336             if ( _CPU_Table.spurious_handler )
    337             {
    338                 handler = (hppa_rtems_isr_entry) _CPU_Table.spurious_handler;
    339                 handler(mask, iframe);
    340             }
    341             else
    342                 hppa_external_interrupt_report_spurious(mask, iframe);
    343         }
    344     }
    345 }
    346156
    347157/*
     
    352162 * Later on, this will allow us to return to the prom.
    353163 * For now, we just ignore 'type_of_halt'
     164 *
     165 * XXX
     166 * NOTE: for gcc, this function must be at the bottom
     167 * of the file, that is because if it is at the top
     168 * of the file, gcc will inline it's calls.  Since
     169 * the function uses the HPPA_ASM_LABEL() macro, when
     170 * gcc inlines it, you get two definitions of the same
     171 * label name, which is an assembly error.
    354172 */
     173
    355174
    356175void
     
    361180    _CPU_ISR_Disable(isrlevel);
    362181
     182    /*
     183     * XXXXX NOTE: This label is only needed that that when
     184     * the simulator stops, it shows the label name specified
     185     */
    363186    HPPA_ASM_LABEL("_hppa_cpu_halt");
    364     HPPA_ASM_BREAK(1, 0);
     187    HPPA_ASM_BREAK(0, 0);
    365188}
     189
Note: See TracChangeset for help on using the changeset viewer.