modified dbg() macro

corrected irq6 handler
reimplemented MFP interrupt LED blinker in C
This commit is contained in:
Markus Fröschle
2014-05-10 13:21:11 +00:00
parent fce807c0d9
commit c628705dd3
4 changed files with 724 additions and 660 deletions

View File

@@ -223,22 +223,22 @@
* If anybody knows of any better way on how to do this - please do! * If anybody knows of any better way on how to do this - please do!
* *
*/ */
.macro mchar st,a,b,c,d,tgt .macro mchar st,a,b,c,d,tgt
\st #\a << 24|\b<<16|\c<<8|\d,\tgt \st #\a << 24|\b<<16|\c<<8|\d,\tgt
.endm .endm
.text .text
_vec_init: _vec_init:
move.l a2,-(sp) // Backup registers move.l a2,-(sp) // Backup registers
mov3q.l #-1,_rt_mod // rt_mod auf super mov3q.l #-1,_rt_mod // rt_mod auf super
clr.l _rt_ssp clr.l _rt_ssp
clr.l _rt_usp clr.l _rt_usp
clr.l _rt_vbr clr.l _rt_vbr
move.l #__RAMBAR0,d0 // exception vectors reside in rambar0 move.l #__RAMBAR0,d0 // exception vectors reside in rambar0
movec d0,VBR movec d0,VBR
move.l d0,a0 move.l d0,a0
move.l a0,a2 move.l a0,a2
init_vec: init_vec:
move.l #256,d0 move.l #256,d0
@@ -509,7 +509,7 @@ irq6: // MFP interrupt from FPGA
movem.l (sp),d0-d1/a0-a1 // restore registers saved above movem.l (sp),d0-d1/a0-a1 // restore registers saved above
lea 4 * 4(sp),sp // adjust stack lea 4 * 4(sp),sp // adjust stack
beq irq6_os // call OS handler bra irq6_os // call OS handler
rte rte
irq6_os: // call native OS irq6 handler irq6_os: // call native OS irq6 handler
@@ -535,36 +535,36 @@ irq6_os: // call native OS irq6 handler
// move.b #0x40,(a5) // clear int6 from edge port // move.b #0x40,(a5) // clear int6 from edge port
// screen adr change timed out? // screen adr change timed out?
move.l _video_sbt,d0 move.l _video_sbt,d0
beq irq6_non_sca // nothing to do if 0 beq irq6_non_sca // nothing to do if 0
sub.l #0x70000000,d0 // substract 14 seconds sub.l #0x70000000,d0 // substract 14 seconds
lea MCF_SLT0_SCNT,a5 lea MCF_SLT0_SCNT,a5
cmp.l (a5),d0 // time reached? cmp.l (a5),d0 // time reached?
ble irq6_non_sca // not yet ble irq6_non_sca // not yet
lea -28(a7),a7 // save more registers lea -28(a7),a7 // save more registers
movem.l d0-d4/a0-a1,(a7) // movem.l d0-d4/a0-a1,(a7) //
clr.l d3 // beginn mit 0 clr.l d3 // beginn mit 0
jsr _flush_and_invalidate_caches jsr _flush_and_invalidate_caches
// eintrag suchen // eintrag suchen
irq6_next_sca: irq6_next_sca:
move.l d3,d0 move.l d3,d0
move.l d0,MCF_MMU_MMUAR // addresse move.l d0,MCF_MMU_MMUAR // addresse
move.l #0x106,d4 move.l #0x106,d4
move.l d4,MCF_MMU_MMUOR // suchen -> move.l d4,MCF_MMU_MMUOR // suchen ->
nop nop
move.l MCF_MMU_MMUOR,d4 move.l MCF_MMU_MMUOR,d4
clr.w d4 clr.w d4
swap d4 swap d4
move.l d4,MCF_MMU_MMUAR move.l d4,MCF_MMU_MMUAR
mvz.w #0x10e,d4 mvz.w #0x10e,d4
move.l d4,MCF_MMU_MMUOR // einträge holen aus mmu move.l d4,MCF_MMU_MMUOR // einträge holen aus mmu
nop nop
move.l MCF_MMU_MMUTR,d4 // ID holen move.l MCF_MMU_MMUTR,d4 // ID holen
lsr.l #2,d4 // bit 9 bis 2 lsr.l #2,d4 // bit 9 bis 2
cmp.w #sca_page_ID,d4 // ist screen change ID? cmp.w #sca_page_ID,d4 // ist screen change ID?
bne irq6_sca_pn // nein -> page keine screen area next bne irq6_sca_pn // nein -> page keine screen area next
// eintrag <EFBFBD>ndern // eintrag <EFBFBD>ndern
add.l #std_mmutr,d0 add.l #std_mmutr,d0
move.l d3,d1 // page 0? move.l d3,d1 // page 0?
@@ -632,18 +632,18 @@ irq6_sca_pn:
move.l #0x2000,d0 move.l #0x2000,d0
move.l d0,_video_tlb // anfangszustand wieder herstellen move.l d0,_video_tlb // anfangszustand wieder herstellen
clr.l _video_sbt // zeit löschen clr.l _video_sbt // zeit löschen
movem.l (sp),d0-d4/a0-a1 // restore registers movem.l (sp),d0-d4/a0-a1 // restore registers
lea 7 * 4(sp),sp lea 7 * 4(sp),sp
irq6_non_sca: irq6_non_sca:
// test auf acsi dma ----------------------------------------------------------------- // test auf acsi dma -----------------------------------------------------------------
lea 0xfffffa0b,a5 lea 0xfffffa0b,a5
bset #7,-4(a5) // int ena bset #7,-4(a5) // int ena
btst.b #7,(a5) // acsi dma int? btst.b #7,(a5) // acsi dma int?
beq non_acsi_dma beq non_acsi_dma
bsr acsi_dma bsr acsi_dma
non_acsi_dma: non_acsi_dma:
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
tst.b (a5) tst.b (a5)
@@ -677,7 +677,7 @@ irq6_2:
blinker:.long 0 blinker:.long 0
.text .text
/* /*
* pseudo dma * pseudo dma
@@ -696,33 +696,33 @@ acsi_dma: // atari dma
acsi_dma_start: acsi_dma_start:
move.l -12(a5),a1 // dma adresse move.l -12(a5),a1 // dma adresse
move.l -8(a5),d0 // byt counter move.l -8(a5),d0 // byt counter
ble acsi_dma_end ble acsi_dma_end
btst.b #0,-16(a5) // write? (dma modus reg) btst.b #0,-16(a5) // write? (dma modus reg)
bne acsi_dma_wl // ja-> bne acsi_dma_wl // ja->
acsi_dma_rl: acsi_dma_rl:
tst.b -4(a5) // dma req? tst.b -4(a5) // dma req?
bpl acsi_dma_finished // nein-> bpl acsi_dma_finished // nein->
move.l (a5),(a1)+ // read 4 bytes move.l (a5),(a1)+ // read 4 bytes
move.l (a5),(a1)+ // read 4 bytes move.l (a5),(a1)+ // read 4 bytes
move.l (a5),(a1)+ // read 4 bytes move.l (a5),(a1)+ // read 4 bytes
move.l (a5),(a1)+ // read 4 bytes move.l (a5),(a1)+ // read 4 bytes
moveq #'.',d1 moveq #'.',d1
move.b d1,MCF_PSC0_PSCTB_8BIT move.b d1,MCF_PSC0_PSCTB_8BIT
sub.l #16,d0 // byt counter -16 sub.l #16,d0 // byt counter -16
bpl acsi_dma_rl bpl acsi_dma_rl
bra acsi_dma_finished bra acsi_dma_finished
acsi_dma_wl: acsi_dma_wl:
tst.b -4(a5) // dma req? tst.b -4(a5) // dma req?
bpl acsi_dma_finished // nein-> bpl acsi_dma_finished // nein->
move.l (a1)+,(a5) // write 4 byts move.l (a1)+,(a5) // write 4 byts
move.l (a1)+,(a5) // write 4 byts move.l (a1)+,(a5) // write 4 byts
move.l (a1)+,(a5) // write 4 byts move.l (a1)+,(a5) // write 4 byts
move.l (a1)+,(a5) // write 4 byts move.l (a1)+,(a5) // write 4 byts
moveq #'.',d1 moveq #'.',d1
move.b d1,MCF_PSC0_PSCTB_8BIT move.b d1,MCF_PSC0_PSCTB_8BIT
sub.l #16,d0 // byt counter -16 sub.l #16,d0 // byt counter -16
bpl acsi_dma_wl bpl acsi_dma_wl
@@ -730,11 +730,11 @@ acsi_dma_finished:
move.l a1,-12(a5) // adresse zur<EFBFBD>ck move.l a1,-12(a5) // adresse zur<EFBFBD>ck
move.l d0,-8(a5) // byt counter zur<EFBFBD>ck move.l d0,-8(a5) // byt counter zur<EFBFBD>ck
acsi_dma_end: acsi_dma_end:
tst.b -4(a5) // dma req? tst.b -4(a5) // dma req?
bmi acsi_dma_start // ja-> bmi acsi_dma_start // ja->
lea 0xfffffa0b,a5 lea 0xfffffa0b,a5
bclr.b #7,4(a5) // clear int in service mfp bclr.b #7,4(a5) // clear int in service mfp
bclr.b #7,(a5) // clear int pending mfp 0xfffffa0b bclr.b #7,(a5) // clear int pending mfp 0xfffffa0b
move.w #0x0d0a,d1 move.w #0x0d0a,d1
move.w d1,MCF_PSC0_PSCTB_8BIT move.w d1,MCF_PSC0_PSCTB_8BIT
@@ -773,7 +773,7 @@ irq7:
* psc3 com PIC MCF * psc3 com PIC MCF
*/ */
handler_psc3: handler_psc3:
.extern _pic_interrupt_handler .extern _pic_interrupt_handler
move.w #0x2700,sr // disable interrupt move.w #0x2700,sr // disable interrupt
lea -4 * 4(sp),sp // save gcc scratch registers lea -4 * 4(sp),sp // save gcc scratch registers
@@ -790,7 +790,7 @@ handler_psc3:
* vbasehi is written to, i.e. when the video base address gets changed * 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 -28(a7),a7 // save registers
movem.l d0-d4/a0-a1,(a7) movem.l d0-d4/a0-a1,(a7)
@@ -802,8 +802,8 @@ handler_gpt0:
// to 60d00000 (FPGA video memory) // to 60d00000 (FPGA video memory)
blt sca_other // blt sca_other //
lea MCF_SLT0_SCNT,a0 lea MCF_SLT0_SCNT,a0
move.l (a0),_video_sbt // save time move.l (a0),_video_sbt // save time
bra video_chg_end bra video_chg_end
// FIXME: don't we need to get out here? // FIXME: don't we need to get out here?
@@ -878,22 +878,22 @@ video_copy_data_loop:
#endif #endif
// eintrag suchen // eintrag suchen
move.l d0,MCF_MMU_MMUAR // adress move.l d0,MCF_MMU_MMUAR // adress
move.l #0x106,d4 move.l #0x106,d4
move.l d4,MCF_MMU_MMUOR // search -> new one will be offered if not found move.l d4,MCF_MMU_MMUOR // search -> new one will be offered if not found
nop nop
move.l MCF_MMU_MMUOR,d4 move.l MCF_MMU_MMUOR,d4
clr.w d4 clr.w d4
swap d4 swap d4
move.l d4,MCF_MMU_MMUAR move.l d4,MCF_MMU_MMUAR
move.l d0,d1 move.l d0,d1
add.l #MCF_MMU_MMUTR_ID(sca_page_ID)|std_mmutr,d0 add.l #MCF_MMU_MMUTR_ID(sca_page_ID)|std_mmutr,d0
add.l #0x60000000|writethrough_mmudr|MCF_MMU_MMUDR_LK,d1 add.l #0x60000000|writethrough_mmudr|MCF_MMU_MMUDR_LK,d1
mvz.w #0x10b,d2 // MMU update mvz.w #0x10b,d2 // MMU update
move.l d0,MCF_MMU_MMUTR move.l d0,MCF_MMU_MMUTR
move.l d1,MCF_MMU_MMUDR move.l d1,MCF_MMU_MMUDR
move.l d2,MCF_MMU_MMUOR // setzen vidoe maped to 60xxx only data move.l d2,MCF_MMU_MMUOR // setzen vidoe maped to 60xxx only data
nop nop
video_chg_2page: video_chg_2page:
// test of adjacent page is needed also // test of adjacent page is needed also
@@ -927,8 +927,8 @@ video_chg_end:
* low-level interrupt service routine for routines registered with * low-level interrupt service routine for routines registered with
* isr_register_handler() * isr_register_handler()
*/ */
.global _lowlevel_isr_handler .global _lowlevel_isr_handler
.extern _isr_execute_handler .extern _isr_execute_handler
_lowlevel_isr_handler: _lowlevel_isr_handler:
move.w #0x2700,sr // disable interrupts move.w #0x2700,sr // disable interrupts

View File

@@ -39,7 +39,7 @@ extern void (*rt_vbr[])(void);
#define IRQ_DEBUG #define IRQ_DEBUG
#if defined(IRQ_DEBUG) #if defined(IRQ_DEBUG)
#define dbg(format, arg...) do { xprintf("DEBUG: " format, ##arg); } while (0) #define dbg(format, arg...) do { xprintf("DEBUG %s(): " format, __FUNCTION__, ##arg); } while (0)
#else #else
#define dbg(format, arg...) do { ; } while (0) #define dbg(format, arg...) do { ; } while (0)
#endif #endif
@@ -50,45 +50,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("%s: interrupt source %d not defined\r\n", __FUNCTION__, 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("%s: level %d and priority %d already used for interrupt source %d!\r\n", __FUNCTION__, 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
@@ -98,10 +98,10 @@ int register_interrupt_handler(uint8_t source, uint8_t level, uint8_t priority,
typedef struct typedef struct
{ {
int vector; int vector;
int (*handler)(void *, void *); int (*handler)(void *, void *);
void *hdev; void *hdev;
void *harg; void *harg;
} ISRENTRY; } ISRENTRY;
ISRENTRY isrtab[MAX_ISR_ENTRY]; ISRENTRY isrtab[MAX_ISR_ENTRY];
@@ -109,132 +109,136 @@ ISRENTRY isrtab[MAX_ISR_ENTRY];
void isr_init(void) void isr_init(void)
{ {
int index; int index;
for (index = 0; index < MAX_ISR_ENTRY; index++) for (index = 0; index < MAX_ISR_ENTRY; index++)
{ {
isrtab[index].vector = 0; isrtab[index].vector = 0;
isrtab[index].handler = 0; isrtab[index].handler = 0;
isrtab[index].hdev = 0; isrtab[index].hdev = 0;
isrtab[index].harg = 0; isrtab[index].harg = 0;
} }
} }
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)
{ {
/* /*
* This function places an interrupt handler in the ISR table, * This function places an interrupt handler in the ISR table,
* thereby registering it so that the low-level handler may call it. * thereby registering it so that the low-level handler may call it.
* *
* The two parameters are intended for the first arg to be a * 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 * pointer to the device itself, and the second a pointer to a data
* structure used by the device driver for that particular device. * structure used by the device driver for that particular device.
*/ */
int index; int index;
if ((vector == 0) || (handler == NULL)) if ((vector == 0) || (handler == NULL))
{ {
dbg("%s: illegal vector or handler!\r\n", __FUNCTION__); 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("%s: already set handler with this vector (%d, %d)\r\n", __FUNCTION__, 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("%s: no available slots to register handler for vector %d\n\r", __FUNCTION__, 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; isrtab[index].vector = 0;
isrtab[index].handler = 0; isrtab[index].handler = 0;
isrtab[index].hdev = 0; isrtab[index].hdev = 0;
isrtab[index].harg = 0; isrtab[index].harg = 0;
return; return;
} }
} }
dbg("%s: no such handler registered (handler=%p\r\n", __FUNCTION__, handler); dbg("no such handler registered (handler=%p\r\n", handler);
} }
bool isr_execute_handler(int vector) bool isr_execute_handler(int vector)
{ {
/* /*
* This routine searches the ISR table for an entry that matches * This routine searches the ISR table for an entry that matches
* 'vector'. If one is found, then 'handler' is executed. * 'vector'. If one is found, then 'handler' is executed.
*/ */
int index; int index;
bool retval = false; bool retval = false;
/* /*
* First 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("%s: no BaS isr handler for vector %d found\r\n", __FUNCTION__, vector); dbg("no BaS isr handler for vector %d found\r\n", vector);
return retval;
return retval;
} }
/*
* PIC interrupt handler for Firebee
*/
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;
@@ -242,106 +246,166 @@ 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("%s:\r\n", __FUNCTION__); 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_RW |
MCF_MMU_MMUOR_ACC;
NOP();
tlb = (MCF_MMU_MMUOR >> 16) & 0xffff;
/*
* retrieve tlb entry with the found TLB entry id
*/
MCF_MMU_MMUAR = tlb;
MCF_MMU_MMUOR =
MCF_MMU_MMUOR_STLB | MCF_MMU_MMUOR_STLB |
MCF_MMU_MMUOR_ADR |
MCF_MMU_MMUOR_RW | MCF_MMU_MMUOR_RW |
MCF_MMU_MMUOR_ACC; MCF_MMU_MMUOR_ACC;
NOP(); NOP();
tlb = (MCF_MMU_MMUOR >> 16) & 0xffff;
asid = (MCF_MMU_MMUTR >> 2) & 0x1fff; /* fetch ASID of page */; /*
if (asid != sca_page_ID) /* check if screen area */ * retrieve tlb entry with the found TLB entry id
{ */
addr += 0x100000; MCF_MMU_MMUAR = tlb;
continue; /* next page */ MCF_MMU_MMUOR =
}
/* modify found TLB entry */
if (addr == 0x0)
{
page_attr =
MCF_MMU_MMUDR_LK |
MCF_MMU_MMUDR_SZ(0) |
MCF_MMU_MMUDR_CM(0) |
MCF_MMU_MMUDR_R |
MCF_MMU_MMUDR_W |
MCF_MMU_MMUDR_X;
}
else
{
page_attr =
MCF_MMU_MMUTR_SG |
MCF_MMU_MMUTR_V;
}
MCF_MMU_MMUTR = addr;
MCF_MMU_MMUDR = page_attr;
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_ACC;
NOP();
asid = (MCF_MMU_MMUTR >> 2) & 0x1fff; /* fetch ASID of page */;
if (asid != sca_page_ID) /* check if screen area */
{
addr += 0x100000;
continue; /* next page */
}
/* modify found TLB entry */
if (addr == 0x0)
{
page_attr =
MCF_MMU_MMUDR_LK |
MCF_MMU_MMUDR_SZ(0) |
MCF_MMU_MMUDR_CM(0) |
MCF_MMU_MMUDR_R |
MCF_MMU_MMUDR_W |
MCF_MMU_MMUDR_X;
}
else
{
page_attr =
MCF_MMU_MMUTR_SG |
MCF_MMU_MMUTR_V;
}
MCF_MMU_MMUTR = addr;
MCF_MMU_MMUDR = page_attr;
MCF_MMU_MMUOR =
MCF_MMU_MMUOR_STLB |
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;
} }
static uint32_t blinker = 0;
/*
* blink the Firebee's LED to show we are still alive
*/
void blink_led(void)
{
if ((blinker++ & 0x80) > 0)
{
MCF_GPIO_PODR_FEC1L |= (1 << 4); /* LED off */
}
else
{
MCF_GPIO_PODR_FEC1L &= ~(1 << 4); /* LED on */
}
}
/*
* Atari MFP interrupt registers.
*
* TODO: should go into a header file
*/
#define FALCON_MFP_IERA *((volatile uint8_t *) 0xfffffa07)
#define FALCON_MFP_IERB *((volatile uint8_t *) 0xfffffa09)
#define FALCON_MFP_IPRA *((volatile uint8_t *) 0xfffffa0b)
#define FALCON_MFP_IPRB *((volatile uint8_t *) 0xfffffa0d)
#define FALCON_MFP_IMRA *((volatile uint8_t *) 0xfffffa13)
#define FALCON_MFP_IMRB *((volatile uint8_t *) 0xfffffa15)
bool irq6_acsi_dma_interrupt(void)
{
dbg("ACSI DMA interrupt\r\n");
/*
* TODO: implement handler
*/
return false;
}
bool irq6_interrupt_handler(uint32_t sf1, uint32_t sf2) bool irq6_interrupt_handler(uint32_t sf1, uint32_t sf2)
{ {
MCF_EPORT_EPFR = 0x40; /* clear int6 from edge port */ bool handled = false;
dbg("%s: irq6!\r\n", __FUNCTION__); 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;
}
return false; /*
* check if ACSI DMA interrupt
*/
if (FALCON_MFP_IERA & (1 << 7))
{
/* ACSI interrupt is enabled */
if (FALCON_MFP_IPRA & (1 << 7))
{
irq6_acsi_dma_interrupt();
handled = true;
}
}
if (FALCON_MFP_IPRA || FALCON_MFP_IPRB)
{
blink_led();
}
return handled;
} }

View File

@@ -44,7 +44,7 @@
#define DBG_MMU #define DBG_MMU
#ifdef DBG_MMU #ifdef DBG_MMU
#define dbg(format, arg...) do { xprintf("DEBUG: " format, ##arg);} while(0) #define dbg(format, arg...) do { xprintf("DEBUG %s(): " format, __FUNCTION__, ##arg);} while(0)
#else #else
#define dbg(format, arg...) do {;} while (0) #define dbg(format, arg...) do {;} while (0)
#endif /* DBG_MMU */ #endif /* DBG_MMU */
@@ -55,19 +55,19 @@
*/ */
inline uint32_t set_asid(uint32_t value) inline uint32_t set_asid(uint32_t value)
{ {
extern long rt_asid; extern long rt_asid;
uint32_t ret = rt_asid; uint32_t ret = rt_asid;
__asm__ __volatile__( __asm__ __volatile__(
"movec %[value],ASID\n\t" "movec %[value],ASID\n\t"
: /* no output */ : /* no output */
: [value] "r" (value) : [value] "r" (value)
: :
); );
rt_asid = value; rt_asid = value;
return ret; return ret;
} }
@@ -77,18 +77,18 @@ inline uint32_t set_asid(uint32_t value)
*/ */
inline uint32_t set_acr0(uint32_t value) inline uint32_t set_acr0(uint32_t value)
{ {
extern uint32_t rt_acr0; extern uint32_t rt_acr0;
uint32_t ret = rt_acr0; uint32_t ret = rt_acr0;
__asm__ __volatile__( __asm__ __volatile__(
"movec %[value],ACR0\n\t" "movec %[value],ACR0\n\t"
: /* not output */ : /* not output */
: [value] "r" (value) : [value] "r" (value)
: :
); );
rt_acr0 = value; rt_acr0 = value;
return ret; return ret;
} }
/* /*
@@ -97,18 +97,18 @@ inline uint32_t set_acr0(uint32_t value)
*/ */
inline uint32_t set_acr1(uint32_t value) inline uint32_t set_acr1(uint32_t value)
{ {
extern uint32_t rt_acr1; extern uint32_t rt_acr1;
uint32_t ret = rt_acr1; uint32_t ret = rt_acr1;
__asm__ __volatile__( __asm__ __volatile__(
"movec %[value],ACR1\n\t" "movec %[value],ACR1\n\t"
: /* not output */ : /* not output */
: [value] "r" (value) : [value] "r" (value)
: :
); );
rt_acr1 = value; rt_acr1 = value;
return ret; return ret;
} }
@@ -118,18 +118,18 @@ inline uint32_t set_acr1(uint32_t value)
*/ */
inline uint32_t set_acr2(uint32_t value) inline uint32_t set_acr2(uint32_t value)
{ {
extern uint32_t rt_acr2; extern uint32_t rt_acr2;
uint32_t ret = rt_acr2; uint32_t ret = rt_acr2;
__asm__ __volatile__( __asm__ __volatile__(
"movec %[value],ACR2\n\t" "movec %[value],ACR2\n\t"
: /* not output */ : /* not output */
: [value] "r" (value) : [value] "r" (value)
: :
); );
rt_acr2 = value; rt_acr2 = value;
return ret; return ret;
} }
/* /*
@@ -138,35 +138,35 @@ inline uint32_t set_acr2(uint32_t value)
*/ */
inline uint32_t set_acr3(uint32_t value) inline uint32_t set_acr3(uint32_t value)
{ {
extern uint32_t rt_acr3; extern uint32_t rt_acr3;
uint32_t ret = rt_acr3; uint32_t ret = rt_acr3;
__asm__ __volatile__( __asm__ __volatile__(
"movec %[value],ACR3\n\t" "movec %[value],ACR3\n\t"
: /* not output */ : /* not output */
: [value] "r" (value) : [value] "r" (value)
: :
); );
rt_acr3 = value; rt_acr3 = value;
return ret; return ret;
} }
inline uint32_t set_mmubar(uint32_t value) inline uint32_t set_mmubar(uint32_t value)
{ {
extern uint32_t rt_mmubar; extern uint32_t rt_mmubar;
uint32_t ret = rt_mmubar; uint32_t ret = rt_mmubar;
__asm__ __volatile__( __asm__ __volatile__(
"movec %[value],MMUBAR\n\t" "movec %[value],MMUBAR\n\t"
: /* no output */ : /* no output */
: [value] "r" (value) : [value] "r" (value)
: /* no clobber */ : /* no clobber */
); );
rt_mmubar = value; rt_mmubar = value;
NOP(); NOP();
return ret; return ret;
} }
@@ -181,229 +181,229 @@ extern uint8_t _FASTRAM_END[];
struct mmu_mapping struct mmu_mapping
{ {
uint32_t phys; uint32_t phys;
uint32_t virt; uint32_t virt;
uint32_t length; uint32_t length;
uint32_t pagesize; uint32_t pagesize;
struct map_flags flags; struct map_flags flags;
}; };
static struct mmu_mapping locked_map[] = static struct mmu_mapping locked_map[] =
{ {
{ {
/* Falcon video memory. Needs special care */ /* Falcon video memory. Needs special care */
0xd00000, 0xd00000,
0x60d00000, 0x60d00000,
0x100000, 0x100000,
MMU_PAGE_SIZE_1M, MMU_PAGE_SIZE_1M,
{ CACHE_WRITETHROUGH, SV_USER, SCA_PAGE_ID, ACCESS_READ | ACCESS_WRITE | ACCESS_EXECUTE }, { CACHE_WRITETHROUGH, SV_USER, SCA_PAGE_ID, ACCESS_READ | ACCESS_WRITE | ACCESS_EXECUTE },
}, },
}; };
static int num_locked_mmu_maps = sizeof(locked_map) / sizeof(struct mmu_mapping); static int num_locked_mmu_maps = sizeof(locked_map) / sizeof(struct mmu_mapping);
static struct mmu_mapping memory_map[] = static struct mmu_mapping memory_map[] =
{ {
/* map system vectors supervisor-protected */ /* map system vectors supervisor-protected */
{ {
0, 0,
0, 0,
0x800, 0x800,
MMU_PAGE_SIZE_1K, MMU_PAGE_SIZE_1K,
{ CACHE_WRITETHROUGH, SV_USER, 0, ACCESS_READ | ACCESS_WRITE | ACCESS_EXECUTE }, { CACHE_WRITETHROUGH, SV_USER, 0, ACCESS_READ | ACCESS_WRITE | ACCESS_EXECUTE },
}, },
{ {
0x800, 0x800,
0x800, 0x800,
0x800, 0x800,
MMU_PAGE_SIZE_1K, MMU_PAGE_SIZE_1K,
{ CACHE_WRITETHROUGH, SV_USER, 0, ACCESS_READ | ACCESS_WRITE | ACCESS_EXECUTE }, { CACHE_WRITETHROUGH, SV_USER, 0, ACCESS_READ | ACCESS_WRITE | ACCESS_EXECUTE },
}, },
{ {
/* when the first 4k are filled with 1k pages, we can switch to 8k pages */ /* when the first 4k are filled with 1k pages, we can switch to 8k pages */
0x1000, 0x1000,
0x1000, 0x1000,
0xff000, 0xff000,
MMU_PAGE_SIZE_8K, MMU_PAGE_SIZE_8K,
{ CACHE_WRITETHROUGH, SV_USER, 0, ACCESS_READ | ACCESS_WRITE | ACCESS_EXECUTE }, { CACHE_WRITETHROUGH, SV_USER, 0, ACCESS_READ | ACCESS_WRITE | ACCESS_EXECUTE },
}, },
{ {
/* arrived at a 1Meg border, we can switch to 1Meg pages */ /* arrived at a 1Meg border, we can switch to 1Meg pages */
0x100000, 0x100000,
0x100000, 0x100000,
0xc00000, 0xc00000,
MMU_PAGE_SIZE_1M, MMU_PAGE_SIZE_1M,
{ CACHE_WRITETHROUGH, SV_USER, 0, ACCESS_READ | ACCESS_WRITE | ACCESS_EXECUTE }, { CACHE_WRITETHROUGH, SV_USER, 0, ACCESS_READ | ACCESS_WRITE | ACCESS_EXECUTE },
}, },
/* Falcon video ram left out intentionally here (see above) */ /* Falcon video ram left out intentionally here (see above) */
{ {
/* ROM */ /* ROM */
0xe00000, 0xe00000,
0xe00000, 0xe00000,
0x100000, 0x100000,
MMU_PAGE_SIZE_1M, MMU_PAGE_SIZE_1M,
{ CACHE_WRITETHROUGH, SV_USER, 0, ACCESS_READ | ACCESS_EXECUTE }, { CACHE_WRITETHROUGH, SV_USER, 0, ACCESS_READ | ACCESS_EXECUTE },
}, },
{ {
/* FASTRAM */ /* FASTRAM */
0x1000000, 0x1000000,
0x1000000, 0x1000000,
_FASTRAM_END - 0x1000000, (uint32_t) _FASTRAM_END - 0x1000000,
MMU_PAGE_SIZE_1M, MMU_PAGE_SIZE_1M,
{ CACHE_WRITETHROUGH, SV_USER, 0, ACCESS_READ | ACCESS_WRITE | ACCESS_EXECUTE }, { CACHE_WRITETHROUGH, SV_USER, 0, ACCESS_READ | ACCESS_WRITE | ACCESS_EXECUTE },
}, },
{ {
/* MBAR */ /* MBAR */
MBAR_ADDRESS, MBAR_ADDRESS,
MBAR_ADDRESS, MBAR_ADDRESS,
0x100000, 0x100000,
MMU_PAGE_SIZE_1M, MMU_PAGE_SIZE_1M,
{ CACHE_NOCACHE_PRECISE, SV_PROTECT, 0, ACCESS_READ | ACCESS_WRITE }, { CACHE_NOCACHE_PRECISE, SV_PROTECT, 0, ACCESS_READ | ACCESS_WRITE },
}, },
{ {
/* RAMBAR0 */ /* RAMBAR0 */
RAMBAR0_ADDRESS, RAMBAR0_ADDRESS,
RAMBAR0_ADDRESS, RAMBAR0_ADDRESS,
(uint32_t) _RAMBAR0_SIZE, (uint32_t) _RAMBAR0_SIZE,
MMU_PAGE_SIZE_1K, MMU_PAGE_SIZE_1K,
{ CACHE_WRITETHROUGH, SV_PROTECT, 0, ACCESS_READ | ACCESS_WRITE | ACCESS_EXECUTE }, { CACHE_WRITETHROUGH, SV_PROTECT, 0, ACCESS_READ | ACCESS_WRITE | ACCESS_EXECUTE },
}, },
{ {
/* RAMBAR1 */ /* RAMBAR1 */
RAMBAR1_ADDRESS, RAMBAR1_ADDRESS,
RAMBAR1_ADDRESS, RAMBAR1_ADDRESS,
(uint32_t) _RAMBAR1_SIZE, (uint32_t) _RAMBAR1_SIZE,
MMU_PAGE_SIZE_1K, MMU_PAGE_SIZE_1K,
{ CACHE_WRITETHROUGH, SV_PROTECT, 0, ACCESS_READ | ACCESS_WRITE | ACCESS_EXECUTE }, { CACHE_WRITETHROUGH, SV_PROTECT, 0, ACCESS_READ | ACCESS_WRITE | ACCESS_EXECUTE },
}, },
{ {
/* SYSTEM SRAM */ /* SYSTEM SRAM */
SYS_SRAM_ADDRESS, SYS_SRAM_ADDRESS,
SYS_SRAM_ADDRESS, SYS_SRAM_ADDRESS,
(uint32_t) _SYS_SRAM_SIZE, (uint32_t) _SYS_SRAM_SIZE,
MMU_PAGE_SIZE_8K, MMU_PAGE_SIZE_8K,
{ CACHE_WRITETHROUGH, SV_PROTECT, 0, ACCESS_READ | ACCESS_WRITE | ACCESS_EXECUTE }, { CACHE_WRITETHROUGH, SV_PROTECT, 0, ACCESS_READ | ACCESS_WRITE | ACCESS_EXECUTE },
}, },
{ {
/* Firebee FPGA registers */ /* Firebee FPGA registers */
(uint32_t) 0xf0000000, (uint32_t) 0xf0000000,
(uint32_t) 0xf0000000, (uint32_t) 0xf0000000,
(uint32_t) 0x08000000, (uint32_t) 0x08000000,
MMU_PAGE_SIZE_1M, MMU_PAGE_SIZE_1M,
{ CACHE_NOCACHE_PRECISE, SV_PROTECT, 0, ACCESS_READ | ACCESS_WRITE }, { CACHE_NOCACHE_PRECISE, SV_PROTECT, 0, ACCESS_READ | ACCESS_WRITE },
}, },
{ {
/* Falcon I/O registers */ /* Falcon I/O registers */
(uint32_t) 0xfff00000, (uint32_t) 0xfff00000,
(uint32_t) 0xfff00000, (uint32_t) 0xfff00000,
(uint32_t) 0x100000, (uint32_t) 0x100000,
MMU_PAGE_SIZE_1M, MMU_PAGE_SIZE_1M,
{ CACHE_NOCACHE_PRECISE, SV_PROTECT, 0, ACCESS_READ | ACCESS_WRITE }, { CACHE_NOCACHE_PRECISE, SV_PROTECT, 0, ACCESS_READ | ACCESS_WRITE },
}, },
{ {
/* the same, but different virtual address */ /* the same, but different virtual address */
(uint32_t) 0x00f00000, (uint32_t) 0x00f00000,
(uint32_t) 0xfff00000, (uint32_t) 0xfff00000,
(uint32_t) 0x100000, (uint32_t) 0x100000,
MMU_PAGE_SIZE_1M, MMU_PAGE_SIZE_1M,
{ CACHE_NOCACHE_PRECISE, SV_PROTECT, ACCESS_READ | ACCESS_WRITE }, { CACHE_NOCACHE_PRECISE, SV_PROTECT, ACCESS_READ | ACCESS_WRITE },
} }
}; };
static int num_mmu_maps = sizeof(memory_map) / sizeof(struct mmu_mapping); static int num_mmu_maps = sizeof(memory_map) / sizeof(struct mmu_mapping);
static struct mmu_mapping *lookup_mapping(uint32_t virt) static struct mmu_mapping *lookup_mapping(uint32_t virt)
{ {
int i; int i;
/* /*
* dumb, for now * dumb, for now
*/ */
for (i = 0; i < num_mmu_maps; i++) for (i = 0; i < num_mmu_maps; i++)
{ {
if (virt >= memory_map[i].virt && virt <= memory_map[i].virt + memory_map[i].length - 1) if (virt >= memory_map[i].virt && virt <= memory_map[i].virt + memory_map[i].length - 1)
return &memory_map[i]; return &memory_map[i];
} }
return NULL; return NULL;
} }
void mmu_init(void) void mmu_init(void)
{ {
extern uint8_t _MMUBAR[]; extern uint8_t _MMUBAR[];
uint32_t MMUBAR = (uint32_t) &_MMUBAR[0]; uint32_t MMUBAR = (uint32_t) &_MMUBAR[0];
int i; int i;
set_asid(0); /* do not use address extension (ASID provides virtual 48 bit addresses */ set_asid(0); /* do not use address extension (ASID provides virtual 48 bit addresses */
/* /*
* need to set data ACRs in a way that supervisor access to all memory regions * need to set data ACRs in a way that supervisor access to all memory regions
* becomes possible. Otherways it might be that the supervisor stack ends up in an unmapped * becomes possible. Otherways it might be that the supervisor stack ends up in an unmapped
* region when further MMU TLB entries force a page steal. This would lead to a double * region when further MMU TLB entries force a page steal. This would lead to a double
* fault since the CPU wouldn't be able to push its exception stack frame during an access * fault since the CPU wouldn't be able to push its exception stack frame during an access
* exception * exception
*/ */
/* set data access attributes in ACR0 and ACR1 */ /* set data access attributes in ACR0 and ACR1 */
set_acr0(ACR_WRITE_PROTECT(0) | /* read and write accesses permitted */ set_acr0(ACR_WRITE_PROTECT(0) | /* read and write accesses permitted */
ACR_SUPERVISOR_PROTECT(0) | /* supervisor and user mode access permitted */ ACR_SUPERVISOR_PROTECT(0) | /* supervisor and user mode access permitted */
ACR_CACHE_MODE(CACHE_WRITETHROUGH) | /* cacheable, write through */ ACR_CACHE_MODE(CACHE_WRITETHROUGH) | /* cacheable, write through */
ACR_ADDRESS_MASK_MODE(1) | /* region 13 MByte */ ACR_ADDRESS_MASK_MODE(1) | /* region 13 MByte */
ACR_S(ACR_S_SUPERVISOR_MODE) | /* memory only visible from supervisor mode */ ACR_S(ACR_S_SUPERVISOR_MODE) | /* memory only visible from supervisor mode */
ACR_E(1) | /* enable ACR */ ACR_E(1) | /* enable ACR */
ACR_ADMSK(0x0a) | /* cover 12 MByte from 0x0 */ ACR_ADMSK(0x0a) | /* cover 12 MByte from 0x0 */
ACR_BA(0)); /* start from 0x0 */ ACR_BA(0)); /* start from 0x0 */
set_acr1(ACR_WRITE_PROTECT(0) | /* read and write accesses permitted */ set_acr1(ACR_WRITE_PROTECT(0) | /* read and write accesses permitted */
ACR_SUPERVISOR_PROTECT(0) | /* supervisor and user mode access permitted */ ACR_SUPERVISOR_PROTECT(0) | /* supervisor and user mode access permitted */
ACR_CACHE_MODE(CACHE_WRITETHROUGH) | /* cacheable, write through */ ACR_CACHE_MODE(CACHE_WRITETHROUGH) | /* cacheable, write through */
ACR_ADDRESS_MASK_MODE(0) | /* region > 16 MByte */ ACR_ADDRESS_MASK_MODE(0) | /* region > 16 MByte */
ACR_S(ACR_S_SUPERVISOR_MODE) | /* memory only visible from supervisor mode */ ACR_S(ACR_S_SUPERVISOR_MODE) | /* memory only visible from supervisor mode */
ACR_E(1) | /* enable ACR */ ACR_E(1) | /* enable ACR */
ACR_ADMSK(0x1f) | /* cover 495 MByte from 0x1000000 */ ACR_ADMSK(0x1f) | /* cover 495 MByte from 0x1000000 */
ACR_BA(0x01000000)); /* all Fast RAM */ ACR_BA(0x01000000)); /* all Fast RAM */
/* /*
* set instruction access attributes in ACR2 and ACR3. This is the same as above, basically: * set instruction access attributes in ACR2 and ACR3. This is the same as above, basically:
* enable supervisor access to all SDRAM * enable supervisor access to all SDRAM
*/ */
set_acr2(ACR_WRITE_PROTECT(0) | set_acr2(ACR_WRITE_PROTECT(0) |
ACR_SUPERVISOR_PROTECT(0) | ACR_SUPERVISOR_PROTECT(0) |
ACR_CACHE_MODE(CACHE_WRITETHROUGH) | ACR_CACHE_MODE(CACHE_WRITETHROUGH) |
ACR_ADDRESS_MASK_MODE(1) | ACR_ADDRESS_MASK_MODE(1) |
ACR_S(ACR_S_SUPERVISOR_MODE) | ACR_S(ACR_S_SUPERVISOR_MODE) |
ACR_E(1) | ACR_E(1) |
ACR_ADMSK(0x0c) | ACR_ADMSK(0x0c) |
ACR_BA(0x0)); ACR_BA(0x0));
set_acr3(ACR_WRITE_PROTECT(0) | set_acr3(ACR_WRITE_PROTECT(0) |
ACR_SUPERVISOR_PROTECT(0) | ACR_SUPERVISOR_PROTECT(0) |
ACR_CACHE_MODE(CACHE_WRITETHROUGH) | ACR_CACHE_MODE(CACHE_WRITETHROUGH) |
ACR_ADDRESS_MASK_MODE(0) | ACR_ADDRESS_MASK_MODE(0) |
ACR_S(ACR_S_SUPERVISOR_MODE) | ACR_S(ACR_S_SUPERVISOR_MODE) |
ACR_E(1) | ACR_E(1) |
ACR_ADMSK(0x1f) | ACR_ADMSK(0x1f) |
ACR_BA(0x0f)); ACR_BA(0x0f));
set_mmubar(MMUBAR + 1); /* set and enable MMUBAR */ set_mmubar(MMUBAR + 1); /* set and enable MMUBAR */
/* clear all MMU TLB entries */ /* clear all MMU TLB entries */
MCF_MMU_MMUOR = MCF_MMU_MMUOR_CA; MCF_MMU_MMUOR = MCF_MMU_MMUOR_CA;
/* map locked TLB entries */ /* map locked TLB entries */
for (i = 0; i < num_locked_mmu_maps; i++) for (i = 0; i < num_locked_mmu_maps; i++)
{ {
mmu_map_page(locked_map[i].virt, locked_map[i].phys, locked_map->pagesize, locked_map->flags); mmu_map_page(locked_map[i].virt, locked_map[i].phys, locked_map->pagesize, locked_map->flags);
if (locked_map[i].flags.page_id == SCA_PAGE_ID) if (locked_map[i].flags.page_id == SCA_PAGE_ID)
{ {
video_tlb = 0x2000; video_tlb = 0x2000;
video_sbt = 0x0; video_sbt = 0x0;
} }
} }
} }
/* /*
@@ -412,101 +412,101 @@ void mmu_init(void)
*/ */
bool access_exception(uint32_t pc, uint32_t format_status) bool access_exception(uint32_t pc, uint32_t format_status)
{ {
int fault_status; int fault_status;
uint32_t fault_address; uint32_t fault_address;
uint32_t mmu_status; uint32_t mmu_status;
/* /*
* extract fault status from format_status exception stack field * extract fault status from format_status exception stack field
*/ */
fault_status = format_status & 0xc030000; fault_status = format_status & 0xc030000;
mmu_status = MCF_MMU_MMUSR; mmu_status = MCF_MMU_MMUSR;
/* /*
* determine if access fault was caused by a TLB miss * determine if access fault was caused by a TLB miss
*/ */
switch (fault_status) switch (fault_status)
{ {
case 0x4010000: /* TLB miss on opword of instruction fetch */ case 0x4010000: /* TLB miss on opword of instruction fetch */
case 0x4020000: /* TLB miss on extension word of instruction fetch */ case 0x4020000: /* TLB miss on extension word of instruction fetch */
fault_address = pc; fault_address = pc;
break; break;
case 0x8020000: /* TLB miss on data write */ case 0x8020000: /* TLB miss on data write */
case 0xc020000: /* TLB miss on data read or read-modify-write */ case 0xc020000: /* TLB miss on data read or read-modify-write */
fault_address = MCF_MMU_MMUAR; fault_address = MCF_MMU_MMUAR;
//dbg("%s: access fault - TLB miss at %p. Fault status = 0x0%x\r\n", __FUNCTION__, pc, fault_status); dbg("access fault - TLB miss at %p. Fault status = 0x0%x\r\n", pc, fault_status);
break; break;
default: default:
return false; return false;
} }
if (mmu_status & MCF_MMU_MMUSR_HIT) /* did the last fault hit in TLB? */ if (mmu_status & MCF_MMU_MMUSR_HIT) /* did the last fault hit in TLB? */
{ {
/* /*
* if yes, then we already mapped that page during a previous turn and this is in fact a bus error * if yes, then we already mapped that page during a previous turn and this is in fact a bus error
*/ */
return false; return false;
} }
else else
{ {
struct mmu_mapping *map; struct mmu_mapping *map;
if ((map = lookup_mapping(fault_address)) != NULL) if ((map = lookup_mapping(fault_address)) != NULL)
{ {
uint32_t mask; uint32_t mask;
switch (map->pagesize) switch (map->pagesize)
{ {
case MMU_PAGE_SIZE_1M: case MMU_PAGE_SIZE_1M:
mask = ~(0x100000 - 1); mask = ~(0x100000 - 1);
break; break;
case MMU_PAGE_SIZE_4K: case MMU_PAGE_SIZE_4K:
mask = ~(0x1000 - 1); mask = ~(0x1000 - 1);
break; break;
case MMU_PAGE_SIZE_8K: case MMU_PAGE_SIZE_8K:
mask = ~(0x2000 - 1); mask = ~(0x2000 - 1);
break; break;
case MMU_PAGE_SIZE_1K: case MMU_PAGE_SIZE_1K:
mask = ~(0x400 - 1); mask = ~(0x400 - 1);
break; break;
} }
mmu_map_page(fault_address & mask, fault_address & mask, map->pagesize, map->flags); mmu_map_page(fault_address & mask, fault_address & mask, map->pagesize, map->flags);
return true; return true;
} }
} }
return false; return false;
} }
void mmu_map_page(uint32_t virt, uint32_t phys, uint32_t map_size, struct map_flags flags) void mmu_map_page(uint32_t virt, uint32_t phys, uint32_t map_size, struct map_flags flags)
{ {
/* /*
* add page to TLB * add page to TLB
*/ */
MCF_MMU_MMUTR = virt | /* virtual address */ MCF_MMU_MMUTR = virt | /* virtual address */
MCF_MMU_MMUTR_ID(flags.page_id) | MCF_MMU_MMUTR_ID(flags.page_id) |
MCF_MMU_MMUTR_SG | /* shared global */ MCF_MMU_MMUTR_SG | /* shared global */
MCF_MMU_MMUTR_V; /* valid */ MCF_MMU_MMUTR_V; /* valid */
MCF_MMU_MMUDR = phys | /* physical address */ MCF_MMU_MMUDR = phys | /* physical address */
MCF_MMU_MMUDR_SZ(map_size) | /* 1 MB page size */ MCF_MMU_MMUDR_SZ(map_size) | /* 1 MB page size */
MCF_MMU_MMUDR_CM(flags.cache_mode) | MCF_MMU_MMUDR_CM(flags.cache_mode) |
(flags.access & ACCESS_READ ? MCF_MMU_MMUDR_R : 0) | /* read access enable */ (flags.access & ACCESS_READ ? MCF_MMU_MMUDR_R : 0) | /* read access enable */
(flags.access & ACCESS_WRITE ? MCF_MMU_MMUDR_W : 0) | /* write access enable */ (flags.access & ACCESS_WRITE ? MCF_MMU_MMUDR_W : 0) | /* write access enable */
(flags.access & ACCESS_EXECUTE ? MCF_MMU_MMUDR_X : 0); /* execute access enable */ (flags.access & ACCESS_EXECUTE ? MCF_MMU_MMUDR_X : 0); /* execute access enable */
MCF_MMU_MMUOR = MCF_MMU_MMUOR_ACC | /* access TLB, data */ MCF_MMU_MMUOR = MCF_MMU_MMUOR_ACC | /* access TLB, data */
MCF_MMU_MMUOR_UAA; /* update allocation address field */ MCF_MMU_MMUOR_UAA; /* update allocation address field */
MCF_MMU_MMUOR = MCF_MMU_MMUOR_ITLB | /* instruction */ MCF_MMU_MMUOR = MCF_MMU_MMUOR_ITLB | /* instruction */
MCF_MMU_MMUOR_ACC | /* access TLB */ MCF_MMU_MMUOR_ACC | /* access TLB */
MCF_MMU_MMUOR_UAA; /* update allocation address field */ MCF_MMU_MMUOR_UAA; /* update allocation address field */
dbg("%s: mapped virt=%p to phys=%p\r\n", __FUNCTION__, virt, phys); dbg("mapped virt=%p to phys=%p\r\n", virt, phys);
} }

View File

@@ -95,10 +95,10 @@ void init_gpio(void)
* *
* for DMA operation * for DMA operation
*/ */
MCF_PAD_PAR_DMA = MCF_PAD_PAR_DMA_PAR_DACK0(0b11) | MCF_PAD_PAR_DMA = MCF_PAD_PAR_DMA_PAR_DACK0(0x3) |
MCF_PAD_PAR_DMA_PAR_DACK1(0b11) | MCF_PAD_PAR_DMA_PAR_DACK1(0x3) |
MCF_PAD_PAR_DMA_PAR_DREQ1(0b11) | MCF_PAD_PAR_DMA_PAR_DREQ1(0x3) |
MCF_PAD_PAR_DMA_PAR_DREQ0(0b11); MCF_PAD_PAR_DMA_PAR_DREQ0(0x3);
/* /*
* configure FEC0 pin assignment on GPIO module as FEC0 * configure FEC0 pin assignment on GPIO module as FEC0