Search
lxdream.org :: lxdream/src/sh4/intc.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/sh4/intc.c
changeset 1:eea311cfd33e
next19:9da7a8e38f9d
author nkeynes
date Sat Aug 21 06:15:49 2004 +0000 (19 years ago)
permissions -rw-r--r--
last change Commit changes into cvs
file annotate diff log raw
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/src/sh4/intc.c Sat Aug 21 06:15:49 2004 +0000
1.3 @@ -0,0 +1,145 @@
1.4 +#include <assert.h>
1.5 +#include "sh4mmio.h"
1.6 +#include "sh4core.h"
1.7 +#include "intc.h"
1.8 +
1.9 +int priorities[12] = {0,0,0,0,0,0,0,0,0,0,0,0};
1.10 +
1.11 +struct intc_sources_t {
1.12 + char *name;
1.13 + uint32_t code;
1.14 + int priority;
1.15 +};
1.16 +
1.17 +#define PRIORITY(which) intc_sources[which].priority
1.18 +#define INTCODE(which) intc_sources[which].code
1.19 +
1.20 +static struct intc_sources_t intc_sources[] = {
1.21 + { "IRQ0", 0x200, 15 }, { "IRQ1", 0x220, 14 }, { "IRQ2", 0x240, 13 },
1.22 + { "IRQ3", 0x260, 12 }, { "IRQ4", 0x280, 11 }, { "IRQ5", 0x2A0, 10 },
1.23 + { "IRQ6", 0x2C0, 9 }, { "IRQ7", 0x2E0, 8 }, { "IRQ8", 0x300, 7 },
1.24 + { "IRQ9", 0x320, 6 }, { "IRQ10",0x340, 5 }, { "IRQ11",0x360, 4 },
1.25 + { "IRQ12",0x380, 3 }, { "IRQ13",0x3A0, 2 }, { "IRQ14",0x3C0, 1 },
1.26 + { "NMI", 0x1C0, 16 }, { "H-UDI",0x600, 0 }, { "GPIOI",0x620, 0 },
1.27 + { "DMTE0",0x640, 0 }, { "DMTE1",0x660, 0 }, { "DMTE2",0x680, 0 },
1.28 + { "DMTE3",0x6A0, 0 }, { "DMTAE",0x6C0, 0 }, { "TUNI0",0x400, 0 },
1.29 + { "TUNI1",0x420, 0 }, { "TUNI2",0x440, 0 }, { "TICPI2",0x460, 0 },
1.30 + { "RTC_ATI",0x480, 0 },{ "RTC_PRI",0x4A0, 0 },{ "RTC_CUI",0x4C0, 0 },
1.31 + { "SCI_ERI",0x4E0, 0 },{ "SCI_RXI",0x500, 0 },{ "SCI_TXI",0x520, 0 },
1.32 + { "SCI_TEI",0x540, 0 },
1.33 + { "SCIF_ERI",0x700, 0 },{ "SCIF_RXI",0x720, 0 },{ "SCIF_BRI",0x740, 0 },
1.34 + { "SCIF_TXI",0x760, 0 },
1.35 + { "WDT_ITI",0x560, 0 },{ "RCMI",0x580, 0 }, { "ROVI",0x5A0, 0 } };
1.36 +
1.37 +int intc_pending[INT_NUM_SOURCES];
1.38 +int intc_num_pending = 0;
1.39 +
1.40 +void mmio_region_INTC_write( uint32_t reg, uint32_t val )
1.41 +{
1.42 + /* Well it saves having to use an intermediate table... */
1.43 + switch( reg ) {
1.44 + case ICR: /* care about this later */
1.45 + break;
1.46 + case IPRA:
1.47 + PRIORITY(INT_TMU_TUNI0) = (val>>12)&0x000F;
1.48 + PRIORITY(INT_TMU_TUNI1) = (val>>8)&0x000F;
1.49 + PRIORITY(INT_TMU_TUNI2) =
1.50 + PRIORITY(INT_TMU_TICPI2) = (val>>4)&0x000F;
1.51 + PRIORITY(INT_RTC_ATI) =
1.52 + PRIORITY(INT_RTC_PRI) =
1.53 + PRIORITY(INT_RTC_CUI) = val&0x000F;
1.54 + break;
1.55 + case IPRB:
1.56 + PRIORITY(INT_WDT_ITI) = (val>>12)&0x000F;
1.57 + PRIORITY(INT_REF_RCMI) =
1.58 + PRIORITY(INT_REF_ROVI) = (val>>8)&0x000F;
1.59 + PRIORITY(INT_SCI_ERI) =
1.60 + PRIORITY(INT_SCI_RXI) =
1.61 + PRIORITY(INT_SCI_TXI) =
1.62 + PRIORITY(INT_SCI_TEI) = (val>>4)&0x000F;
1.63 + /* Bits 0-3 reserved */
1.64 + break;
1.65 + case IPRC:
1.66 + PRIORITY(INT_GPIO) = (val>>12)&0x000F;
1.67 + PRIORITY(INT_DMA_DMTE0) =
1.68 + PRIORITY(INT_DMA_DMTE1) =
1.69 + PRIORITY(INT_DMA_DMTE2) =
1.70 + PRIORITY(INT_DMA_DMTE3) =
1.71 + PRIORITY(INT_DMA_DMAE) = (val>>8)&0x000F;
1.72 + PRIORITY(INT_SCIF_ERI) =
1.73 + PRIORITY(INT_SCIF_RXI) =
1.74 + PRIORITY(INT_SCIF_BRI) =
1.75 + PRIORITY(INT_SCIF_TXI) = (val>>4)&0x000F;
1.76 + PRIORITY(INT_HUDI) = val&0x000F;
1.77 + break;
1.78 + }
1.79 + MMIO_WRITE( INTC, reg, val );
1.80 +}
1.81 +
1.82 +int32_t mmio_region_INTC_read( uint32_t reg )
1.83 +{
1.84 + return MMIO_READ( INTC, reg );
1.85 +}
1.86 +
1.87 +/* We basically maintain a priority queue here, raise_interrupt adds an entry,
1.88 + * accept_interrupt takes it off. At the moment this is does as a simple
1.89 + * ordered array, on the basis that in practice there's unlikely to be more
1.90 + * than one at a time. There are lots of ways to optimize this if it turns out
1.91 + * to be necessary, but I'd doubt it will be...
1.92 + */
1.93 +
1.94 +void intc_raise_interrupt( int which )
1.95 +{
1.96 + int i, j, pri;
1.97 +
1.98 + pri = PRIORITY(which);
1.99 + if( pri == 0 ) return; /* masked off */
1.100 +
1.101 + for( i=0; i<intc_num_pending; i++ ) {
1.102 + if( intc_pending[i] == which ) return; /* Don't queue more than once */
1.103 + if( PRIORITY(intc_pending[i]) > pri ||
1.104 + (PRIORITY(intc_pending[i]) == pri &&
1.105 + intc_pending[i] < which))
1.106 + break;
1.107 + }
1.108 + /* i == insertion point */
1.109 + for( j=intc_num_pending; j > i; j-- )
1.110 + intc_pending[j] = intc_pending[j-1];
1.111 + intc_pending[i] = which;
1.112 +
1.113 + if( i == intc_num_pending && (sh4r.sr&SR_BL)==0 && SH4_INTMASK() < pri )
1.114 + sh4r.int_pending = 1;
1.115 +
1.116 + intc_num_pending++;
1.117 +}
1.118 +
1.119 +uint32_t intc_accept_interrupt( void )
1.120 +{
1.121 + assert(intc_num_pending > 0);
1.122 + intc_num_pending--;
1.123 + if( intc_num_pending > 0 )
1.124 + sh4r.int_pending = PRIORITY(intc_pending[intc_num_pending-1]);
1.125 + else
1.126 + sh4r.int_pending = 0;
1.127 + return INTCODE(intc_pending[intc_num_pending]);
1.128 +}
1.129 +
1.130 +void intc_mask_changed( void )
1.131 +{
1.132 + if( intc_num_pending > 0 && (sh4r.sr&SR_BL)==0 &&
1.133 + SH4_INTMASK() < PRIORITY(intc_pending[intc_num_pending-1]) )
1.134 + sh4r.int_pending = 1;
1.135 + else sh4r.int_pending = 0;
1.136 +}
1.137 +
1.138 +
1.139 +char *intc_get_interrupt_name( int code )
1.140 +{
1.141 + return intc_sources[code].name;
1.142 +}
1.143 +
1.144 +void intc_reset( void )
1.145 +{
1.146 + intc_num_pending = 0;
1.147 + sh4r.int_pending = 0;
1.148 +}
.