fixed a few MMU quirks

This commit is contained in:
Markus Fröschle
2014-09-17 05:28:16 +00:00
parent e7fa2b5bff
commit 0801adb0c0
6 changed files with 316 additions and 308 deletions

View File

@@ -39,7 +39,7 @@
#error "unknown machine!" #error "unknown machine!"
#endif /* MACHINE_FIREBEE */ #endif /* MACHINE_FIREBEE */
#define DBG_DMA //#define DBG_DMA
#ifdef DBG_DMA #ifdef DBG_DMA
#define dbg(format, arg...) do { xprintf("DEBUG: %s(): " format, __FUNCTION__, ##arg); } while (0) #define dbg(format, arg...) do { xprintf("DEBUG: %s(): " format, __FUNCTION__, ##arg); } while (0)
#else #else

View File

@@ -32,7 +32,7 @@ void cacr_set(uint32_t value)
__asm__ __volatile__("movec %0, cacr\n\t" __asm__ __volatile__("movec %0, cacr\n\t"
: /* output */ : /* output */
: "r" (rt_cacr) : "r" (rt_cacr)
: /* clobbers */); : "memory" /* clobbers */);
} }
uint32_t cacr_get(void) uint32_t cacr_get(void)
@@ -44,35 +44,41 @@ uint32_t cacr_get(void)
void disable_data_cache(void) void disable_data_cache(void)
{ {
flush_and_invalidate_caches(); flush_and_invalidate_caches();
cacr_set(cacr_get() | CF_CACR_DCINVA); cacr_set((cacr_get() | CF_CACR_DCINVA) & ~CF_CACR_DEC);
}
void disable_instruction_cache(void)
{
flush_and_invalidate_caches();
cacr_set((cacr_get() | CF_CACR_ICINVA) & ~CF_CACR_IEC);
} }
void enable_data_cache(void) void enable_data_cache(void)
{ {
cacr_set(cacr_get() & ~CF_CACR_DCINVA); cacr_set(cacr_get() & ~CF_CACR_DCINVA);
} }
void flush_and_invalidate_caches(void) void flush_and_invalidate_caches(void)
{ {
__asm__ __volatile__( __asm__ __volatile__(
" clr.l d0 \n\t" " clr.l d0 \n\t"
" clr.l d1 \n\t" " clr.l d1 \n\t"
" move.l d0,a0 \n\t" " move.l d0,a0 \n\t"
"cfa_setloop: \n\t" "cfa_setloop: \n\t"
" cpushl bc,(a0) | flush\n\t" " cpushl bc,(a0) | flush\n\t"
" lea 0x10(a0),a0 | index+1\n\t" " lea 0x10(a0),a0 | index+1\n\t"
" addq.l #1,d1 | index+1\n\t" " addq.l #1,d1 | index+1\n\t"
" cmpi.w #512,d1 | all sets?\n\t" " cmpi.w #512,d1 | all sets?\n\t"
" bne.s cfa_setloop | no->\n\t" " bne.s cfa_setloop | no->\n\t"
" clr.l d1 \n\t" " clr.l d1 \n\t"
" addq.l #1,d0 \n\t" " addq.l #1,d0 \n\t"
" move.l d0,a0 \n\t" " move.l d0,a0 \n\t"
" cmpi.w #4,d0 | all ways?\n\t" " cmpi.w #4,d0 | all ways?\n\t"
" bne.s cfa_setloop | no->\n\t" " bne.s cfa_setloop | no->\n\t"
/* input */ : /* input */ :
/* output */ : /* output */ :
/* clobber */ : "cc", "d0", "d1", "a0" /* clobber */ : "cc", "d0", "d1", "a0"
); );
} }
@@ -92,35 +98,35 @@ void flush_icache_range(void *address, size_t size)
if (start_set > end_set) { if (start_set > end_set) {
/* from the begining to the lowest address */ /* from the begining to the lowest address */
for (set = 0; set <= end_set; set += (0x10 - 3)) { for (set = 0; set <= end_set; set += (0x10 - 3)) {
__asm__ __volatile__( __asm__ __volatile__(
" cpushl ic,(%[set]) \n\t" " cpushl ic,(%[set]) \n\t"
" addq.l #1,%[set] \n\t" " addq.l #1,%[set] \n\t"
" cpushl ic,(%[set]) \n\t" " cpushl ic,(%[set]) \n\t"
" addq.l #1,%[set] \n\t" " addq.l #1,%[set] \n\t"
" cpushl ic,(%[set]) \n\t" " cpushl ic,(%[set]) \n\t"
" addq.l #1,%[set] \n\t" " addq.l #1,%[set] \n\t"
" cpushl ic,(%[set]) \n\t" " cpushl ic,(%[set]) \n\t"
: /* output parameters */ : /* output parameters */
: [set] "a" (set) /* input parameters */ : [set] "a" (set) /* input parameters */
: "cc" /* clobbered registers */ : "cc" /* clobbered registers */
); );
} }
/* next loop will finish the cache ie pass the hole */ /* next loop will finish the cache ie pass the hole */
end_set = LAST_ICACHE_ADDR; end_set = LAST_ICACHE_ADDR;
} }
for (set = start_set; set <= end_set; set += (0x10 - 3)) { for (set = start_set; set <= end_set; set += (0x10 - 3)) {
__asm__ __volatile__( __asm__ __volatile__(
" cpushl ic,(%[set]) \n\t" " cpushl ic,(%[set]) \n\t"
" addq.l #1,%[set] \n\t" " addq.l #1,%[set] \n\t"
" cpushl ic,(%[set]) \n\t" " cpushl ic,(%[set]) \n\t"
" addq.l #1,%[set] \n\t" " addq.l #1,%[set] \n\t"
" cpushl ic,(%[set]) \n\t" " cpushl ic,(%[set]) \n\t"
" addq.l #1,%[set] \n\t" " addq.l #1,%[set] \n\t"
" cpushl ic,(%[set])" " cpushl ic,(%[set])"
: /* output parameters */ : /* output parameters */
: [set] "a" (set) : [set] "a" (set)
: "cc" : "cc"
); );
} }
} }
@@ -142,37 +148,37 @@ void flush_dcache_range(void *address, size_t size)
if (start_set > end_set) { if (start_set > end_set) {
/* from the begining to the lowest address */ /* from the begining to the lowest address */
for (set = 0; set <= end_set; set += (0x10 - 3)) for (set = 0; set <= end_set; set += (0x10 - 3))
{ {
__asm__ __volatile__( __asm__ __volatile__(
" cpushl dc,(%[set]) \n\t" " cpushl dc,(%[set]) \n\t"
" addq.l #1,%[set] \n\t" " addq.l #1,%[set] \n\t"
" cpushl dc,(%[set]) \n\t" " cpushl dc,(%[set]) \n\t"
" addq.l #1,%[set] \n\t" " addq.l #1,%[set] \n\t"
" cpushl dc,(%[set]) \n\t" " cpushl dc,(%[set]) \n\t"
" addq.l #1,%[set] \n\t" " addq.l #1,%[set] \n\t"
" cpushl dc,(%[set]) \n\t" " cpushl dc,(%[set]) \n\t"
: /* output parameters */ : /* output parameters */
: [set] "a" (set) : [set] "a" (set)
: "cc" /* clobbered registers */ : "cc" /* clobbered registers */
); );
} }
/* next loop will finish the cache ie pass the hole */ /* next loop will finish the cache ie pass the hole */
end_set = LAST_DCACHE_ADDR; end_set = LAST_DCACHE_ADDR;
} }
for (set = start_set; set <= end_set; set += (0x10 - 3)) for (set = start_set; set <= end_set; set += (0x10 - 3))
{ {
__asm__ __volatile__( __asm__ __volatile__(
" cpushl dc,(%[set]) \n\t" " cpushl dc,(%[set]) \n\t"
" addq.l #1,%[set] \n\t" " addq.l #1,%[set] \n\t"
" cpushl dc,(%[set]) \n\t" " cpushl dc,(%[set]) \n\t"
" addq%.l #1,%[set] \n\t" " addq%.l #1,%[set] \n\t"
" cpushl dc,(%[set]) \n\t" " cpushl dc,(%[set]) \n\t"
" addq.l #1,%[set] \n\t" " addq.l #1,%[set] \n\t"
" cpushl dc,(%[set]) \n\t" " cpushl dc,(%[set]) \n\t"
: /* output parameters */ : /* output parameters */
: [set] "a" (set) : [set] "a" (set)
: "cc" /* clobbered registers */ : "cc" /* clobbered registers */
); );
} }
} }

View File

@@ -758,15 +758,17 @@ irq7:
/* /*
* general purpose timer 0 (GPT0): video change, later also others. GPT0 is used as * general purpose timer 0 (GPT0): video change, later also others.
* input trigger. It is connected to the TIN0 signal of the FPGA and triggers everytime *
* vbasehi is written to, i.e. when the video base address gets changed * GPT0 is used as input trigger. It is connected to the TIN0 signal of
* the FPGA and triggers everytime vbasehi is written to, i.e.
* when the video base address gets changed
*/ */
handler_gpt0: handler_gpt0:
move #0x2700,sr // disable interrupts move #0x2700,sr // disable interrupts
lea -28(a7),a7 // save registers lea -7 * 4(sp),sp // save registers
movem.l d0-d4/a0-a1,(a7) movem.l d0-d4/a0-a1,(sp)
mvz.b vbasehi,d0 // screen base address high mvz.b vbasehi,d0 // screen base address high
cmp.w #2,d0 // screen base lower than 0x20000? cmp.w #2,d0 // screen base lower than 0x20000?
@@ -779,7 +781,7 @@ handler_gpt0:
move.l (a0),_video_sbt // save time move.l (a0),_video_sbt // save time
// FIXME: don't we need to get out here? // FIXME: don't we need to get out here?
bra video_chg_end // bra video_chg_end
sca_other: sca_other:
lsl.l #8,d0 // build new screen start address from Atari register contents lsl.l #8,d0 // build new screen start address from Atari register contents
@@ -840,7 +842,7 @@ video_chg_2page:
mvz.w 0xffff82a8,d1 // VDB: vertical display begin mvz.w 0xffff82a8,d1 // VDB: vertical display begin
sub.l d1,d2 // number of lines sub.l d1,d2 // number of lines
mulu d2,d4 // times number of words per line mulu d2,d4 // times number of words per line
add.l d4,d0 // video gr<EFBFBD>sse add.l d4,d0 // video memory end address
cmp.l #__STRAM_END,d0 // start address > end of STRAM? cmp.l #__STRAM_END,d0 // start address > end of STRAM?
bge video_chg_end // yes - we're finished bge video_chg_end // yes - we're finished
@@ -853,8 +855,8 @@ video_chg_2page:
jsr _flush_and_invalidate_caches jsr _flush_and_invalidate_caches
video_chg_end: video_chg_end:
lea MCF_GPT0_GMS,a0 // clear interrupt lea MCF_GPT0_GMS,a0 // disable and reenable timer
bclr.b #0,3(a0) bclr.b #0,3(a0) // input capture
nop nop
bset.b #0,3(a0) bset.b #0,3(a0)

View File

@@ -27,7 +27,7 @@
#include "bas_printf.h" #include "bas_printf.h"
#include "wait.h" #include "wait.h"
#define FPGA_DEBUG // #define FPGA_DEBUG
#if defined(FPGA_DEBUG) #if defined(FPGA_DEBUG)
#define dbg(format, arg...) do { xprintf("DEBUG: %s(): " format, __FUNCTION__, ##arg); } while (0) #define dbg(format, arg...) do { xprintf("DEBUG: %s(): " format, __FUNCTION__, ##arg); } while (0)
#else #else

View File

@@ -38,7 +38,7 @@
extern void (*rt_vbr[])(void); extern void (*rt_vbr[])(void);
#define VBR rt_vbr #define VBR rt_vbr
#define IRQ_DEBUG //#define IRQ_DEBUG
#if defined(IRQ_DEBUG) #if defined(IRQ_DEBUG)
#define dbg(format, arg...) do { xprintf("DEBUG %s(): " format, __FUNCTION__, ##arg); } while (0) #define dbg(format, arg...) do { xprintf("DEBUG %s(): " format, __FUNCTION__, ##arg); } while (0)
#else #else
@@ -51,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
@@ -99,10 +99,10 @@ int register_interrupt_handler(uint8_t source, uint8_t level, uint8_t priority,
struct isrentry struct isrentry
{ {
int vector; int vector;
int (*handler)(void *, void *); int (*handler)(void *, void *);
void *hdev; void *hdev;
void *harg; void *harg;
}; };
static struct isrentry isrtab[MAX_ISR_ENTRY]; /* list of interrupt service routines */ static struct isrentry isrtab[MAX_ISR_ENTRY]; /* list of interrupt service routines */
@@ -112,7 +112,7 @@ static struct isrentry isrtab[MAX_ISR_ENTRY]; /* list of interrupt service
*/ */
void isr_init(void) void isr_init(void)
{ {
memset(isrtab, 0, sizeof(isrtab)); memset(isrtab, 0, sizeof(isrtab));
} }
/* /*
@@ -125,56 +125,56 @@ void isr_init(void)
*/ */
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; 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)
{ {
memset(&isrtab[index], 0, sizeof(struct isrentry)); memset(&isrtab[index], 0, sizeof(struct isrentry));
return; return;
} }
} }
dbg("no such handler registered (handler=%p\r\n", handler); dbg("no such handler registered (handler=%p\r\n", handler);
} }
/* /*
@@ -183,27 +183,27 @@ void isr_remove_handler(int (*handler)(void *, void *))
*/ */
bool isr_execute_handler(int vector) bool isr_execute_handler(int vector)
{ {
int index; int index;
bool retval = false; 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;
} }
/* /*
@@ -211,24 +211,24 @@ bool isr_execute_handler(int vector)
*/ */
int pic_interrupt_handler(void *arg1, void *arg2) int pic_interrupt_handler(void *arg1, void *arg2)
{ {
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);
} }
return 1; return 1;
} }
@@ -237,93 +237,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;
} }
@@ -332,16 +332,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 */
} }
} }
/* /*
@@ -359,45 +359,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;
} }

View File

@@ -62,7 +62,7 @@
#error "unknown machine!" #error "unknown machine!"
#endif /* MACHINE_FIREBEE */ #endif /* MACHINE_FIREBEE */
#define DEBUG_MMU // #define DEBUG_MMU
#ifdef DEBUG_MMU #ifdef DEBUG_MMU
#define dbg(format, arg...) do { xprintf("DEBUG (%s()): " format, __FUNCTION__, ##arg);} while(0) #define dbg(format, arg...) do { xprintf("DEBUG (%s()): " format, __FUNCTION__, ##arg);} while(0)
#else #else
@@ -377,7 +377,7 @@ void mmu_init(void)
* Map (locked) the second last MB of physical SDRAM (this is where BaS .data and .bss reside) to the same * Map (locked) the second last MB of physical SDRAM (this is where BaS .data and .bss reside) to the same
* virtual address. This is also used (completely) when BaS is in RAM * virtual address. This is also used (completely) when BaS is in RAM
*/ */
flags.cache_mode = CACHE_WRITETHROUGH; flags.cache_mode = CACHE_COPYBACK;
flags.access = ACCESS_READ | ACCESS_WRITE | ACCESS_EXECUTE; flags.access = ACCESS_READ | ACCESS_WRITE | ACCESS_EXECUTE;
mmu_map_page(SDRAM_START + SDRAM_SIZE - 0X00200000, SDRAM_START + SDRAM_SIZE - 0X00200000, MMU_PAGE_SIZE_1M, &flags); mmu_map_page(SDRAM_START + SDRAM_SIZE - 0X00200000, SDRAM_START + SDRAM_SIZE - 0X00200000, MMU_PAGE_SIZE_1M, &flags);