Search
lxdream.org :: lxdream/src/sh4/intc.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/sh4/intc.c
changeset 20:3ffb66aa25c7
prev19:9da7a8e38f9d
next31:495e480360d7
author nkeynes
date Thu Dec 22 13:28:16 2005 +0000 (14 years ago)
permissions -rw-r--r--
last change Add scif.c (oops)
Convert interrupts to be level-triggered rather than edge-triggered
(although shouldn't be any visible difference)
view annotate diff log raw
     1 #include <assert.h>
     2 #include "sh4mmio.h"
     3 #include "sh4core.h"
     4 #include "intc.h"
     6 int priorities[12] = {0,0,0,0,0,0,0,0,0,0,0,0};
     8 struct intc_sources_t {
     9     char *name;
    10     uint32_t code;
    11     int priority;
    12 };
    14 #define PRIORITY(which) intc_sources[which].priority
    15 #define INTCODE(which) intc_sources[which].code
    17 static struct intc_sources_t intc_sources[] = {
    18     { "IRQ0", 0x200, 15 }, { "IRQ1", 0x220, 14 }, { "IRQ2", 0x240, 13 },
    19     { "IRQ3", 0x260, 12 }, { "IRQ4", 0x280, 11 }, { "IRQ5", 0x2A0, 10 },
    20     { "IRQ6", 0x2C0, 9 },  { "IRQ7", 0x2E0, 8 },  { "IRQ8", 0x300, 7 },
    21     { "IRQ9", 0x320, 6 },  { "IRQ10",0x340, 5 },  { "IRQ11",0x360, 4 },
    22     { "IRQ12",0x380, 3 },  { "IRQ13",0x3A0, 2 },  { "IRQ14",0x3C0, 1 },
    23     { "NMI", 0x1C0, 16 },  { "H-UDI",0x600, 0 },  { "GPIOI",0x620, 0 },
    24     { "DMTE0",0x640, 0 },  { "DMTE1",0x660, 0 },  { "DMTE2",0x680, 0 },
    25     { "DMTE3",0x6A0, 0 },  { "DMTAE",0x6C0, 0 },  { "TUNI0",0x400, 0 },
    26     { "TUNI1",0x420, 0 },  { "TUNI2",0x440, 0 },  { "TICPI2",0x460, 0 },
    27     { "RTC_ATI",0x480, 0 },{ "RTC_PRI",0x4A0, 0 },{ "RTC_CUI",0x4C0, 0 },
    28     { "SCI_ERI",0x4E0, 0 },{ "SCI_RXI",0x500, 0 },{ "SCI_TXI",0x520, 0 },
    29     { "SCI_TEI",0x540, 0 },
    30     { "SCIF_ERI",0x700, 0 },{ "SCIF_RXI",0x720, 0 },{ "SCIF_BRI",0x740, 0 },
    31     { "SCIF_TXI",0x760, 0 },
    32     { "WDT_ITI",0x560, 0 },{ "RCMI",0x580, 0 },   { "ROVI",0x5A0, 0 } };
    34 int intc_pending[INT_NUM_SOURCES];
    35 int intc_num_pending = 0;
    37 void mmio_region_INTC_write( uint32_t reg, uint32_t val )
    38 {
    39     /* Well it saves having to use an intermediate table... */
    40     switch( reg ) {
    41         case ICR: /* care about this later */
    42             break;
    43         case IPRA:
    44             PRIORITY(INT_TMU_TUNI0) = (val>>12)&0x000F;
    45             PRIORITY(INT_TMU_TUNI1) = (val>>8)&0x000F;
    46             PRIORITY(INT_TMU_TUNI2) =
    47                 PRIORITY(INT_TMU_TICPI2) = (val>>4)&0x000F;
    48             PRIORITY(INT_RTC_ATI) =
    49                 PRIORITY(INT_RTC_PRI) =
    50                 PRIORITY(INT_RTC_CUI) = val&0x000F;
    51             break;
    52         case IPRB:
    53             PRIORITY(INT_WDT_ITI) = (val>>12)&0x000F;
    54             PRIORITY(INT_REF_RCMI) =
    55                 PRIORITY(INT_REF_ROVI) = (val>>8)&0x000F;
    56             PRIORITY(INT_SCI_ERI) =
    57                 PRIORITY(INT_SCI_RXI) =
    58                 PRIORITY(INT_SCI_TXI) =
    59                 PRIORITY(INT_SCI_TEI) = (val>>4)&0x000F;
    60             /* Bits 0-3 reserved */
    61             break;
    62         case IPRC:
    63             PRIORITY(INT_GPIO) = (val>>12)&0x000F;
    64             PRIORITY(INT_DMA_DMTE0) =
    65                 PRIORITY(INT_DMA_DMTE1) =
    66                 PRIORITY(INT_DMA_DMTE2) =
    67                 PRIORITY(INT_DMA_DMTE3) =
    68                 PRIORITY(INT_DMA_DMAE) = (val>>8)&0x000F;
    69             PRIORITY(INT_SCIF_ERI) =
    70                 PRIORITY(INT_SCIF_RXI) =
    71                 PRIORITY(INT_SCIF_BRI) =
    72                 PRIORITY(INT_SCIF_TXI) = (val>>4)&0x000F;
    73             PRIORITY(INT_HUDI) = val&0x000F;
    74             break;
    75     }
    76     MMIO_WRITE( INTC, reg, val );
    77 }
    79 int32_t mmio_region_INTC_read( uint32_t reg )
    80 {
    81     return MMIO_READ( INTC, reg );
    82 }
    84 /* We basically maintain a priority queue here, raise_interrupt adds an entry,
    85  * accept_interrupt takes it off. At the moment this is does as a simple
    86  * ordered array, on the basis that in practice there's unlikely to be more
    87  * than one at a time. There are lots of ways to optimize this if it turns out
    88  * to be necessary, but I'd doubt it will be...
    89  */
    91 void intc_raise_interrupt( int which )
    92 {
    93     int i, j, pri;
    95     pri = PRIORITY(which);
    96     if( pri == 0 ) return; /* masked off */
    98     for( i=0; i<intc_num_pending; i++ ) {
    99         if( intc_pending[i] == which ) return; /* Don't queue more than once */
   100         if( PRIORITY(intc_pending[i]) > pri ||
   101             (PRIORITY(intc_pending[i]) == pri &&
   102              intc_pending[i] < which))
   103             break;
   104     }
   105     /* i == insertion point */
   106     for( j=intc_num_pending; j > i; j-- )
   107         intc_pending[j] = intc_pending[j-1];
   108     intc_pending[i] = which;
   110     if( i == intc_num_pending && (sh4r.sr&SR_BL)==0 && SH4_INTMASK() < pri )
   111         sh4r.int_pending = 1;
   113     intc_num_pending++;
   114 }
   116 void intc_clear_interrupt( int which )
   117 {
   118     int i;
   119     for( i=intc_num_pending-1; i>=0; i-- ) {
   120 	if( intc_pending[i] == which ) {
   121 	    /* Shift array contents down */
   122 	    while( i < intc_num_pending-1 ) {
   123 		intc_pending[i] = intc_pending[++i];
   124 	    }
   125 	    intc_num_pending--;
   126 	    if( intc_num_pending == 0 )
   127 		sh4r.int_pending = 0;
   128 	    else
   129 		sh4r.int_pending = PRIORITY(intc_pending[intc_num_pending-1]);
   130 	    break;
   131 	}
   132     }
   134 }
   136 uint32_t intc_accept_interrupt( void )
   137 {
   138     assert(intc_num_pending > 0);
   139     return INTCODE(intc_pending[intc_num_pending-1]);
   140     /*
   141     intc_num_pending--;
   142     if( intc_num_pending > 0 )
   143         sh4r.int_pending = PRIORITY(intc_pending[intc_num_pending-1]);
   144     else
   145         sh4r.int_pending = 0;
   146     return INTCODE(intc_pending[intc_num_pending]);
   147     */
   148 }
   150 void intc_mask_changed( void )
   151 {   
   152     if( intc_num_pending > 0 && (sh4r.sr&SR_BL)==0 &&
   153         SH4_INTMASK() < PRIORITY(intc_pending[intc_num_pending-1]) )
   154         sh4r.int_pending = 1;
   155     else sh4r.int_pending = 0;
   156 }
   159 char *intc_get_interrupt_name( int code )
   160 {
   161     return intc_sources[code].name;
   162 }
   164 void intc_reset( void )
   165 {
   166     intc_num_pending = 0;
   167     sh4r.int_pending = 0;
   168 }
.