modified dbg() macro
corrected irq6 handler reimplemented MFP interrupt LED blinker in C
This commit is contained in:
238
sys/exceptions.S
238
sys/exceptions.S
@@ -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
|
||||||
@@ -255,7 +255,7 @@ init_vec_loop:
|
|||||||
|
|
||||||
lea access_exception(pc),a1 // set illegal access exception handler
|
lea access_exception(pc),a1 // set illegal access exception handler
|
||||||
move.l a1,0x08(a0)
|
move.l a1,0x08(a0)
|
||||||
|
|
||||||
.extern _get_bas_drivers
|
.extern _get_bas_drivers
|
||||||
// trap #0 (without any parameters for now) is used to provide BaS' driver addresses to the OS
|
// trap #0 (without any parameters for now) is used to provide BaS' driver addresses to the OS
|
||||||
lea _get_bas_drivers(pc),a1
|
lea _get_bas_drivers(pc),a1
|
||||||
@@ -336,17 +336,17 @@ std_exc_vec:
|
|||||||
beq noprint
|
beq noprint
|
||||||
move.l 4 * 4 + 8 + 4(sp),-(sp) // pc at exception
|
move.l 4 * 4 + 8 + 4(sp),-(sp) // pc at exception
|
||||||
move.l d0,-(sp) // provide it to xprintf()
|
move.l d0,-(sp) // provide it to xprintf()
|
||||||
pea exception_text
|
pea exception_text
|
||||||
jsr _xprintf // call xprintf()
|
jsr _xprintf // call xprintf()
|
||||||
add.l #3*4,sp // adjust stack
|
add.l #3*4,sp // adjust stack
|
||||||
noprint:
|
noprint:
|
||||||
|
|
||||||
movem.l (sp),d0-d1/a0-a1 // restore registers
|
movem.l (sp),d0-d1/a0-a1 // restore registers
|
||||||
lea 4 * 4(sp),sp
|
lea 4 * 4(sp),sp
|
||||||
#endif /* DBG_EXC */
|
#endif /* DBG_EXC */
|
||||||
|
|
||||||
add.l _rt_vbr,d0 // + VBR
|
add.l _rt_vbr,d0 // + VBR
|
||||||
move.l d0,a5
|
move.l d0,a5
|
||||||
move.l (a5),d0 // fetch exception routine address
|
move.l (a5),d0 // fetch exception routine address
|
||||||
|
|
||||||
move.l 4(sp),a5 // restore a5
|
move.l 4(sp),a5 // restore a5
|
||||||
@@ -382,7 +382,7 @@ access_exception:
|
|||||||
lea -4*4(sp),sp
|
lea -4*4(sp),sp
|
||||||
movem.l d0-d1/a0-a1,(sp)
|
movem.l d0-d1/a0-a1,(sp)
|
||||||
|
|
||||||
|
|
||||||
lea 4*4(sp),a0 // original stack pointer
|
lea 4*4(sp),a0 // original stack pointer
|
||||||
|
|
||||||
move.l (a0),-(sp) // format status word
|
move.l (a0),-(sp) // format status word
|
||||||
@@ -402,7 +402,7 @@ access_exception:
|
|||||||
|
|
||||||
bus_error:
|
bus_error:
|
||||||
bra std_exc_vec
|
bra std_exc_vec
|
||||||
|
|
||||||
zero_divide:
|
zero_divide:
|
||||||
move.l a0,-(a7)
|
move.l a0,-(a7)
|
||||||
move.l d0,-(a7)
|
move.l d0,-(a7)
|
||||||
@@ -430,9 +430,9 @@ zd_nal: cmp.w #0x3c,d0 // immediate?
|
|||||||
zd_end:
|
zd_end:
|
||||||
move.l a0,12(a7)
|
move.l a0,12(a7)
|
||||||
move.l (a7)+,d0
|
move.l (a7)+,d0
|
||||||
move.l (a7)+,a0
|
move.l (a7)+,a0
|
||||||
rte
|
rte
|
||||||
|
|
||||||
irq1:
|
irq1:
|
||||||
irq 0x64,1,0x02
|
irq 0x64,1,0x02
|
||||||
|
|
||||||
@@ -458,7 +458,7 @@ irq5: // irq5 is tied to PCI INTC# and PCI INTD# on the M5484LITE
|
|||||||
jsr _irq5_handler // call C handler routine
|
jsr _irq5_handler // call C handler routine
|
||||||
|
|
||||||
movem.l (sp),d0-d1/a0-a1 // restore registers
|
movem.l (sp),d0-d1/a0-a1 // restore registers
|
||||||
lea 4*4(sp),sp
|
lea 4*4(sp),sp
|
||||||
|
|
||||||
rte // return from exception
|
rte // return from exception
|
||||||
|
|
||||||
@@ -466,7 +466,7 @@ irq5text:
|
|||||||
.ascii "IRQ5!"
|
.ascii "IRQ5!"
|
||||||
.dc.b 13,10,0
|
.dc.b 13,10,0
|
||||||
|
|
||||||
irq6:
|
irq6:
|
||||||
irq 0x74,5,0x20
|
irq 0x74,5,0x20
|
||||||
|
|
||||||
irq7: // irq7 is tied to PCI INTA# and PCI INTB# on the M5484LITE
|
irq7: // irq7 is tied to PCI INTA# and PCI INTB# on the M5484LITE
|
||||||
@@ -479,7 +479,7 @@ irq7: // irq7 is tied to PCI INTA# and PCI INTB# on the M5484LITE
|
|||||||
jsr _irq7_handler // call C handler routine
|
jsr _irq7_handler // call C handler routine
|
||||||
|
|
||||||
movem.l (sp),d0-d1/a0-a1 // restore registers
|
movem.l (sp),d0-d1/a0-a1 // restore registers
|
||||||
lea 4*4(sp),sp
|
lea 4*4(sp),sp
|
||||||
|
|
||||||
rte // return from exception
|
rte // return from exception
|
||||||
|
|
||||||
@@ -495,7 +495,7 @@ irq5:
|
|||||||
|
|
||||||
irq6: // MFP interrupt from FPGA
|
irq6: // MFP interrupt from FPGA
|
||||||
move.w #0x2700,sr // disable interrupts
|
move.w #0x2700,sr // disable interrupts
|
||||||
|
|
||||||
lea -4 * 4(sp),sp // save gcc scratch registers
|
lea -4 * 4(sp),sp // save gcc scratch registers
|
||||||
movem.l d0-d1/a0-a1,(sp)
|
movem.l d0-d1/a0-a1,(sp)
|
||||||
|
|
||||||
@@ -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?
|
||||||
@@ -574,10 +574,10 @@ irq6_os: // call native OS irq6 handler
|
|||||||
irq6_sca_pn0:
|
irq6_sca_pn0:
|
||||||
add.l #writethrough_mmudr|MCF_MMU_MMUDR_LK,d1 // page wt and locked
|
add.l #writethrough_mmudr|MCF_MMU_MMUDR_LK,d1 // page wt and locked
|
||||||
irq6_sca_pn1c:
|
irq6_sca_pn1c:
|
||||||
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 // setze tlb data only
|
move.l d2,MCF_MMU_MMUOR // setze tlb data only
|
||||||
nop
|
nop
|
||||||
// page copy
|
// page copy
|
||||||
move.l d3,a0
|
move.l d3,a0
|
||||||
@@ -616,7 +616,7 @@ wait_dma_finished:
|
|||||||
cmp.l #6,d0
|
cmp.l #6,d0
|
||||||
bne wait_dma_finished
|
bne wait_dma_finished
|
||||||
#else
|
#else
|
||||||
irq6_vcd0_loop:
|
irq6_vcd0_loop:
|
||||||
move.l (a0)+,(a1)+ // page copy
|
move.l (a0)+,(a1)+ // page copy
|
||||||
move.l (a0)+,(a1)+
|
move.l (a0)+,(a1)+
|
||||||
move.l (a0)+,(a1)+
|
move.l (a0)+,(a1)+
|
||||||
@@ -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)
|
||||||
@@ -652,7 +652,7 @@ non_acsi_dma:
|
|||||||
bne irq6_1
|
bne irq6_1
|
||||||
movem.l (a7),d0/a5
|
movem.l (a7),d0/a5
|
||||||
addq.l #8,a7
|
addq.l #8,a7
|
||||||
rte
|
rte
|
||||||
irq6_1:
|
irq6_1:
|
||||||
lea MCF_GPIO_PODR_FEC1L,a5
|
lea MCF_GPIO_PODR_FEC1L,a5
|
||||||
bclr.b #4,(a5) // led on
|
bclr.b #4,(a5) // led on
|
||||||
@@ -677,7 +677,7 @@ irq6_2:
|
|||||||
blinker:.long 0
|
blinker:.long 0
|
||||||
|
|
||||||
|
|
||||||
.text
|
.text
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* pseudo dma
|
* pseudo dma
|
||||||
@@ -685,7 +685,7 @@ blinker:.long 0
|
|||||||
acsi_dma: // atari dma
|
acsi_dma: // atari dma
|
||||||
move.l a1,-(a7)
|
move.l a1,-(a7)
|
||||||
move.l d1,-(a7)
|
move.l d1,-(a7)
|
||||||
|
|
||||||
lea MCF_PSC0_PSCTB_8BIT,a1 // ++ vr
|
lea MCF_PSC0_PSCTB_8BIT,a1 // ++ vr
|
||||||
mchar move.l, 'D,'M','A,'\ ,(a1)
|
mchar move.l, 'D,'M','A,'\ ,(a1)
|
||||||
//move.l #"DMA ",(a1)
|
//move.l #"DMA ",(a1)
|
||||||
@@ -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
|
|
||||||
move.b d1,MCF_PSC0_PSCTB_8BIT
|
|
||||||
|
|
||||||
sub.l #16,d0 // byt counter -16
|
moveq #'.',d1
|
||||||
bpl acsi_dma_rl
|
move.b d1,MCF_PSC0_PSCTB_8BIT
|
||||||
bra acsi_dma_finished
|
|
||||||
|
sub.l #16,d0 // byt counter -16
|
||||||
|
bpl acsi_dma_rl
|
||||||
|
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,15 +730,15 @@ 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
|
||||||
|
|
||||||
move.l (a7)+,d1
|
move.l (a7)+,d1
|
||||||
move.l (a7)+,a1
|
move.l (a7)+,a1
|
||||||
rts
|
rts
|
||||||
@@ -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
|
||||||
|
|||||||
482
sys/interrupts.c
482
sys/interrupts.c
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
656
sys/mmu.c
656
sys/mmu.c
@@ -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,332 +181,332 @@ 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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* handle an access error
|
* handle an access error
|
||||||
* upper level routine called from access_exception inside exceptions.S
|
* upper level routine called from access_exception inside exceptions.S
|
||||||
*/
|
*/
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user