fixed a few MMU quirks
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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 */
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user