refactored

This commit is contained in:
Markus Fröschle
2014-09-06 21:29:55 +00:00
parent 307c5368b4
commit 22760eb9b8

View File

@@ -27,6 +27,7 @@
#include "MCF5475.h" #include "MCF5475.h"
#include "bas_utils.h" #include "bas_utils.h"
#include "bas_printf.h" #include "bas_printf.h"
#include "bas_string.h"
#include "exceptions.h" #include "exceptions.h"
#include "interrupts.h" #include "interrupts.h"
#include "bas_printf.h" #include "bas_printf.h"
@@ -50,45 +51,45 @@ extern void (*rt_vbr[])(void);
*/ */
int register_interrupt_handler(uint8_t source, uint8_t level, uint8_t priority, uint8_t intr, void (*handler)(void)) int register_interrupt_handler(uint8_t source, uint8_t level, uint8_t priority, uint8_t intr, void (*handler)(void))
{ {
int ipl; int ipl;
int i; int i;
volatile uint8_t *ICR = &MCF_INTC_ICR01 - 1; volatile uint8_t *ICR = &MCF_INTC_ICR01 - 1;
uint8_t lp; uint8_t lp;
source &= 63; source &= 63;
priority &= 7; priority &= 7;
if (source < 1 || source > 63) if (source < 1 || source > 63)
{ {
dbg("interrupt source %d not defined\r\n", source); dbg("interrupt source %d not defined\r\n", source);
return -1; return -1;
} }
lp = MCF_INTC_ICR_IL(level) | MCF_INTC_ICR_IP(priority); lp = MCF_INTC_ICR_IL(level) | MCF_INTC_ICR_IP(priority);
/* check if this combination is already set somewhere */ /* check if this combination is already set somewhere */
for (i = 1; i < 64; i++) for (i = 1; i < 64; i++)
{ {
if (ICR[i] == lp) if (ICR[i] == lp)
{ {
dbg("level %d and priority %d already used for interrupt source %d!\r\n", dbg("level %d and priority %d already used for interrupt source %d!\r\n",
level, priority, i); level, priority, i);
return -1; return -1;
} }
} }
/* disable interrupts */ /* disable interrupts */
ipl = set_ipl(7); ipl = set_ipl(7);
VBR[64 + source] = handler; /* first 64 vectors are system exceptions */ VBR[64 + source] = handler; /* first 64 vectors are system exceptions */
/* set level and priority in interrupt controller */ /* set level and priority in interrupt controller */
ICR[source] = lp; ICR[source] = lp;
/* set interrupt mask to where it was before */ /* set interrupt mask to where it was before */
set_ipl(ipl); set_ipl(ipl);
return 0; return 0;
} }
#ifndef MAX_ISR_ENTRY #ifndef MAX_ISR_ENTRY
@@ -96,124 +97,113 @@ int register_interrupt_handler(uint8_t source, uint8_t level, uint8_t priority,
#endif #endif
typedef struct struct isrentry
{ {
int vector; int vector;
int (*handler)(void *, void *); int (*handler)(void *, void *);
void *hdev; void *hdev;
void *harg; void *harg;
} ISRENTRY; };
ISRENTRY isrtab[MAX_ISR_ENTRY];
static struct isrentry isrtab[MAX_ISR_ENTRY]; /* list of interrupt service routines */
/*
* clear the table of interrupt service handlers
*/
void isr_init(void) void isr_init(void)
{ {
int index; memset(isrtab, 0, sizeof(isrtab));
for (index = 0; index < MAX_ISR_ENTRY; index++)
{
isrtab[index].vector = 0;
isrtab[index].handler = 0;
isrtab[index].hdev = 0;
isrtab[index].harg = 0;
}
} }
/*
* This function places an interrupt handler in the ISR table,
* thereby registering it so that the low-level handler may call it.
*
* The two parameters are intended for the first arg to be a
* pointer to the device itself, and the second a pointer to a data
* structure used by the device driver for that particular device.
*/
int isr_register_handler(int vector, int (*handler)(void *, void *), void *hdev, void *harg) int isr_register_handler(int vector, int (*handler)(void *, void *), void *hdev, void *harg)
{ {
/* int index;
* This function places an interrupt handler in the ISR table,
* thereby registering it so that the low-level handler may call it.
*
* The two parameters are intended for the first arg to be a
* pointer to the device itself, and the second a pointer to a data
* structure used by the device driver for that particular device.
*/
int index;
if ((vector == 0) || (handler == NULL)) if ((vector == 0) || (handler == NULL))
{ {
dbg("illegal vector or handler!\r\n"); dbg("illegal vector or handler!\r\n");
return false; return false;
} }
for (index = 0; index < MAX_ISR_ENTRY; index++) for (index = 0; index < MAX_ISR_ENTRY; index++)
{ {
if (isrtab[index].vector == vector) if (isrtab[index].vector == vector)
{ {
/* one cross each, only! */ /* one cross each, only! */
dbg("already set handler with this vector (%d, %d)\r\n", vector); dbg("already set handler with this vector (%d, %d)\r\n", vector);
return false; return false;
} }
if (isrtab[index].vector == 0) if (isrtab[index].vector == 0)
{ {
isrtab[index].vector = vector; isrtab[index].vector = vector;
isrtab[index].handler = handler; isrtab[index].handler = handler;
isrtab[index].hdev = hdev; isrtab[index].hdev = hdev;
isrtab[index].harg = harg; isrtab[index].harg = harg;
return true; return true;
} }
} }
dbg("no available slots to register handler for vector %d\n\r", vector); dbg("no available slots to register handler for vector %d\n\r", vector);
return false; /* no available slots */ return false; /* no available slots */
} }
void isr_remove_handler(int (*handler)(void *, void *)) void isr_remove_handler(int (*handler)(void *, void *))
{ {
/* /*
* This routine removes from the ISR table all * This routine removes from the ISR table all
* entries that matches 'handler'. * entries that matches 'handler'.
*/ */
int index; int index;
for (index = 0; index < MAX_ISR_ENTRY; index++) for (index = 0; index < MAX_ISR_ENTRY; index++)
{ {
if (isrtab[index].handler == handler) if (isrtab[index].handler == handler)
{ {
isrtab[index].vector = 0; memset(&isrtab[index], 0, sizeof(struct isrentry));
isrtab[index].handler = 0;
isrtab[index].hdev = 0;
isrtab[index].harg = 0;
return; return;
} }
} }
dbg("no such handler registered (handler=%p\r\n", handler); dbg("no such handler registered (handler=%p\r\n", handler);
} }
/*
* This routine searches the ISR table for an entry that matches
* 'vector'. If one is found, then 'handler' is executed.
*/
bool isr_execute_handler(int vector) bool isr_execute_handler(int vector)
{ {
/* int index;
* This routine searches the ISR table for an entry that matches bool retval = false;
* 'vector'. If one is found, then 'handler' is executed.
*/
int index;
bool retval = false;
/* /*
* locate a BaS Interrupt Service Routine handler. * locate a BaS Interrupt Service Routine handler.
*/ */
for (index = 0; index < MAX_ISR_ENTRY; index++) for (index = 0; index < MAX_ISR_ENTRY; index++)
{ {
if (isrtab[index].vector == vector) if (isrtab[index].vector == vector)
{ {
retval = true; retval = true;
if (isrtab[index].handler(isrtab[index].hdev, isrtab[index].harg)) if (isrtab[index].handler(isrtab[index].hdev, isrtab[index].harg))
{ {
return retval; return retval;
} }
} }
} }
dbg("no BaS isr handler for vector %d found\r\n", vector); dbg("no BaS isr handler for vector %d found\r\n", vector);
return retval; return retval;
} }
/* /*
@@ -221,24 +211,24 @@ bool isr_execute_handler(int vector)
*/ */
void pic_interrupt_handler(void) void pic_interrupt_handler(void)
{ {
uint8_t rcv_byte; uint8_t rcv_byte;
rcv_byte = MCF_PSC3_PSCRB_8BIT; rcv_byte = MCF_PSC3_PSCRB_8BIT;
if (rcv_byte == 2) // PIC requests RTC data if (rcv_byte == 2) // PIC requests RTC data
{ {
uint8_t *rtc_reg= (uint8_t *) 0xffff8961; uint8_t *rtc_reg = (uint8_t *) 0xffff8961;
uint8_t *rtc_data = (uint8_t *) 0xffff8963; uint8_t *rtc_data = (uint8_t *) 0xffff8963;
int index = 0; int index = 0;
xprintf("PIC interrupt requesting RTC data\r\n"); xprintf("PIC interrupt requesting RTC data\r\n");
MCF_PSC3_PSCTB_8BIT = 0x82; // header byte to PIC MCF_PSC3_PSCTB_8BIT = 0x82; // header byte to PIC
do do
{ {
*rtc_reg = 0; *rtc_reg = 0;
MCF_PSC3_PSCTB_8BIT = *rtc_data; MCF_PSC3_PSCTB_8BIT = *rtc_data;
} while (index++ < 64); } while (index++ < 64);
} }
} }
extern int32_t video_sbt; extern int32_t video_sbt;
@@ -246,93 +236,93 @@ extern int32_t video_tlb;
void video_addr_timeout(void) void video_addr_timeout(void)
{ {
uint32_t addr = 0x0L; uint32_t addr = 0x0L;
uint32_t *src; uint32_t *src;
uint32_t *dst; uint32_t *dst;
uint32_t asid; uint32_t asid;
dbg("video address timeout\r\n"); dbg("video address timeout\r\n");
flush_and_invalidate_caches(); flush_and_invalidate_caches();
do do
{ {
uint32_t tlb; uint32_t tlb;
uint32_t page_attr; uint32_t page_attr;
/* /*
* search tlb entry id for addr (if not available, the MMU * search tlb entry id for addr (if not available, the MMU
* will provide a new one based on its LRU algorithm) * will provide a new one based on its LRU algorithm)
*/ */
MCF_MMU_MMUAR = addr; MCF_MMU_MMUAR = addr;
MCF_MMU_MMUOR = MCF_MMU_MMUOR =
MCF_MMU_MMUOR_STLB | MCF_MMU_MMUOR_STLB |
MCF_MMU_MMUOR_RW | MCF_MMU_MMUOR_RW |
MCF_MMU_MMUOR_ACC; MCF_MMU_MMUOR_ACC;
NOP(); NOP();
tlb = (MCF_MMU_MMUOR >> 16) & 0xffff; tlb = (MCF_MMU_MMUOR >> 16) & 0xffff;
/* /*
* retrieve tlb entry with the found TLB entry id * retrieve tlb entry with the found TLB entry id
*/ */
MCF_MMU_MMUAR = tlb; MCF_MMU_MMUAR = tlb;
MCF_MMU_MMUOR = MCF_MMU_MMUOR =
MCF_MMU_MMUOR_STLB | MCF_MMU_MMUOR_STLB |
MCF_MMU_MMUOR_ADR | MCF_MMU_MMUOR_ADR |
MCF_MMU_MMUOR_RW | MCF_MMU_MMUOR_RW |
MCF_MMU_MMUOR_ACC; MCF_MMU_MMUOR_ACC;
NOP(); NOP();
asid = (MCF_MMU_MMUTR >> 2) & 0x1fff; /* fetch ASID of page */; asid = (MCF_MMU_MMUTR >> 2) & 0x1fff; /* fetch ASID of page */;
if (asid != sca_page_ID) /* check if screen area */ if (asid != sca_page_ID) /* check if screen area */
{ {
addr += 0x100000; addr += 0x100000;
continue; /* next page */ continue; /* next page */
} }
/* modify found TLB entry */ /* modify found TLB entry */
if (addr == 0x0) if (addr == 0x0)
{ {
page_attr = page_attr =
MCF_MMU_MMUDR_LK | MCF_MMU_MMUDR_LK |
MCF_MMU_MMUDR_SZ(0) | MCF_MMU_MMUDR_SZ(0) |
MCF_MMU_MMUDR_CM(0) | MCF_MMU_MMUDR_CM(0) |
MCF_MMU_MMUDR_R | MCF_MMU_MMUDR_R |
MCF_MMU_MMUDR_W | MCF_MMU_MMUDR_W |
MCF_MMU_MMUDR_X; MCF_MMU_MMUDR_X;
} }
else else
{ {
page_attr = page_attr =
MCF_MMU_MMUTR_SG | MCF_MMU_MMUTR_SG |
MCF_MMU_MMUTR_V; MCF_MMU_MMUTR_V;
} }
MCF_MMU_MMUTR = addr; MCF_MMU_MMUTR = addr;
MCF_MMU_MMUDR = page_attr; MCF_MMU_MMUDR = page_attr;
MCF_MMU_MMUOR = MCF_MMU_MMUOR =
MCF_MMU_MMUOR_STLB | MCF_MMU_MMUOR_STLB |
MCF_MMU_MMUOR_ADR | MCF_MMU_MMUOR_ADR |
MCF_MMU_MMUOR_ACC | MCF_MMU_MMUOR_ACC |
MCF_MMU_MMUOR_UAA; MCF_MMU_MMUOR_UAA;
NOP(); NOP();
dst = (uint32_t *) 0x60000000 + addr; dst = (uint32_t *) 0x60000000 + addr;
src = (uint32_t *) addr; src = (uint32_t *) addr;
while (dst < (uint32_t *) 0x60000000 + addr + 0x10000) while (dst < (uint32_t *) 0x60000000 + addr + 0x10000)
{ {
*dst++ = *src++; *dst++ = *src++;
*dst++ = *src++; *dst++ = *src++;
*dst++ = *src++; *dst++ = *src++;
*dst++ = *src++; *dst++ = *src++;
} }
addr += 0x100000; addr += 0x100000;
} while (addr < 0xd00000); } while (addr < 0xd00000);
video_tlb = 0x2000; video_tlb = 0x2000;
video_sbt = 0; video_sbt = 0;
} }
@@ -341,16 +331,16 @@ void video_addr_timeout(void)
*/ */
void blink_led(void) void blink_led(void)
{ {
static uint16_t blinker = 0; static uint16_t blinker = 0;
if ((blinker++ & 0x80) > 0) if ((blinker++ & 0x80) > 0)
{ {
MCF_GPIO_PODR_FEC1L |= (1 << 4); /* LED off */ MCF_GPIO_PODR_FEC1L |= (1 << 4); /* LED off */
} }
else else
{ {
MCF_GPIO_PODR_FEC1L &= ~(1 << 4); /* LED on */ MCF_GPIO_PODR_FEC1L &= ~(1 << 4); /* LED on */
} }
} }
/* /*
@@ -368,45 +358,45 @@ void blink_led(void)
bool irq6_acsi_dma_interrupt(void) bool irq6_acsi_dma_interrupt(void)
{ {
dbg("ACSI DMA interrupt\r\n"); dbg("ACSI DMA interrupt\r\n");
/* /*
* TODO: implement handler * TODO: implement handler
*/ */
return false; return false;
} }
bool irq6_interrupt_handler(uint32_t sf1, uint32_t sf2) bool irq6_interrupt_handler(uint32_t sf1, uint32_t sf2)
{ {
bool handled = false; bool handled = false;
MCF_EPORT_EPFR |= (1 << 6); /* clear int6 from edge port */ MCF_EPORT_EPFR |= (1 << 6); /* clear int6 from edge port */
if (video_sbt != 0 && (video_sbt - 0x70000000) > MCF_SLT0_SCNT) if (video_sbt != 0 && (video_sbt - 0x70000000) > MCF_SLT0_SCNT)
{ {
video_addr_timeout(); video_addr_timeout();
handled = true; handled = true;
} }
/* /*
* check if ACSI DMA interrupt * check if ACSI DMA interrupt
*/ */
if (FALCON_MFP_IERA & (1 << 7)) if (FALCON_MFP_IERA & (1 << 7))
{ {
/* ACSI interrupt is enabled */ /* ACSI interrupt is enabled */
if (FALCON_MFP_IPRA & (1 << 7)) if (FALCON_MFP_IPRA & (1 << 7))
{ {
irq6_acsi_dma_interrupt(); irq6_acsi_dma_interrupt();
handled = true; handled = true;
} }
} }
if (FALCON_MFP_IPRA || FALCON_MFP_IPRB) if (FALCON_MFP_IPRA || FALCON_MFP_IPRB)
{ {
blink_led(); blink_led();
} }
return handled; return handled;
} }