www.pudn.com > ucosii_core.rar > intc.c, change:2006-08-24,size:3950b
#include "includes.h"
#include <stdio.h>
#include "mips.h"
#include "regs.h"
#include "ops.h"
#include "mipsregs.h"
#define IRQ_MAX (IRQ_GPIO_0 + NUM_GPIO)
static struct {
void (*handler)(unsigned int);
unsigned int arg;
} irq_table[IRQ_MAX];
static void default_handler(unsigned int arg)
{
printf("PANIC:illigeal interrupt expired:%d\n", arg);
while(1);
}
static unsigned int dma_irq_mask = 0;
static unsigned int gpio_irq_mask[4] = {0};
void enable_irq(unsigned int irq)
{
register unsigned int t;
if ((irq >= IRQ_GPIO_0) && (irq <= IRQ_GPIO_0 + NUM_GPIO)) {
__gpio_unmask_irq(irq - IRQ_GPIO_0);
t = (irq - IRQ_GPIO_0) >> 5;
gpio_irq_mask[t] |= (1 << ((irq - IRQ_GPIO_0) & 0x1f));
__intc_unmask_irq(IRQ_GPIO0 - t);
} else if ((irq >= IRQ_DMA_0) && (irq <= IRQ_DMA_0 + NUM_DMA)) {
__dmac_channel_enable_irq(irq - IRQ_DMA_0);
dma_irq_mask |= (1 << (irq - IRQ_DMA_0));
__intc_unmask_irq(IRQ_DMAC);
} else if (irq < 32)
__intc_unmask_irq(irq);
}
void disable_irq(unsigned int irq)
{
register unsigned int t;
if ((irq >= IRQ_GPIO_0) && (irq <= IRQ_GPIO_0 + NUM_GPIO)) {
__gpio_mask_irq(irq - IRQ_GPIO_0);
t = (irq - IRQ_GPIO_0) >> 5;
gpio_irq_mask[t] &= ~(1 << ((irq - IRQ_GPIO_0) & 0x1f));
if (!gpio_irq_mask[t])
__intc_mask_irq(IRQ_GPIO0 - t);
} else if ((irq >= IRQ_DMA_0) && (irq <= IRQ_DMA_0 + NUM_DMA)) {
__dmac_channel_disable_irq(irq - IRQ_DMA_0);
dma_irq_mask &= ~(1 << (irq - IRQ_DMA_0));
if (!dma_irq_mask)
__intc_mask_irq(IRQ_DMAC);
} else if (irq < 32)
__intc_mask_irq(irq);
}
void ack_irq(unsigned int irq)
{
__intc_ack_irq(irq);
if ((irq >= IRQ_GPIO_0) && (irq <= IRQ_GPIO_0 + NUM_GPIO)) {
__intc_ack_irq(IRQ_GPIO0 - ((irq - IRQ_GPIO_0)>>5));
__gpio_ack_irq(irq - IRQ_GPIO_0);
} else if ((irq >= IRQ_DMA_0) && (irq <= IRQ_DMA_0 + NUM_DMA)) {
__intc_ack_irq(IRQ_DMAC);
} else if (irq < 32)
__intc_ack_irq(irq);
}
static unsigned long ipl;
static int intc_irq(void)
{
register int irq = 0;
ipl |= REG_INTC_IPR;
if (ipl == 0)
return -1;
/* find out the real irq defined in irq_xxx.c */
for (irq=31;irq>=0;irq--)
if (ipl & (1 << irq))
break;
if (irq < 0)
return -1;
ipl &= ~(1 << irq);
switch (irq) {
case IRQ_GPIO0:
irq = __gpio_group_irq(0) + IRQ_GPIO_0;
break;
case IRQ_GPIO1:
irq = __gpio_group_irq(1) + IRQ_GPIO_0 + 32;
break;
case IRQ_GPIO2:
irq = __gpio_group_irq(2) + IRQ_GPIO_0 + 64;
break;
case IRQ_GPIO3:
irq = __gpio_group_irq(3) + IRQ_GPIO_0 + 96;
break;
case IRQ_DMAC:
irq = __dmac_get_irq() + IRQ_DMA_0;
break;
}
return irq;
}
void intc_init(void)
{
unsigned int i;
ipl = 0;
for (i=0;i<IRQ_MAX;i++) {
disable_irq(i);
irq_table[i].handler = default_handler;
irq_table[i].arg = i;
}
}
int request_irq(unsigned int irq, void (*handler)(unsigned int), unsigned arg)
{
if (irq > IRQ_MAX)
return -1;
if (irq_table[irq].handler != default_handler)
return -1;
irq_table[irq].handler = handler;
irq_table[irq].arg = arg;
enable_irq(irq);
}
void free_irq(unsigned int irq)
{
disable_irq(irq);
irq_table[irq].handler = default_handler;
irq_table[irq].arg = irq;
}
typedef struct CP0_tstREGS
{
U32 wStatus;
U32 wCause;
}CP0_tstREGS;
void C_vINTHandler(CP0_tstREGS *pstC0)
{
register int irq = intc_irq();
//printf("irq:%d\n", irq);
if (irq < 0)
return;
switch (irq) {
case IRQ_OST0:
__ost_clear_uf(0);
break;
}
ack_irq(irq);
irq_table[irq].handler(irq_table[irq].arg);
}
void cli(void)
{
register unsigned int t;
t = read_c0_status();
t &= ~1;
write_c0_status(t);
}
unsigned int mips_get_sr(void)
{
unsigned int t = read_c0_status();
return t;
}
void sti(void)
{
register unsigned int t;
t = read_c0_status();
t |= 1;
t &= ~2;
write_c0_status(t);
}
unsigned int spin_lock_irqsave(void)
{
register unsigned int t;
t = read_c0_status();
write_c0_status((t&(~1)));
return t;
}
void spin_unlock_irqrestore(unsigned int val)
{
write_c0_status(val);
}