From 4f81b597a639dc1ac7173efc4f3cd0656dbcf7e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Fr=C3=B6schle?= Date: Sat, 21 Jun 2014 06:21:41 +0000 Subject: [PATCH] reverted to last released to make it work again --- BaS_gcc/sys/exceptions.S | 812 +++++++++++++++++++++++---------------- BaS_gcc/sys/mmu.c | 665 +++++++++++++------------------- 2 files changed, 746 insertions(+), 731 deletions(-) diff --git a/BaS_gcc/sys/exceptions.S b/BaS_gcc/sys/exceptions.S index a0ae926..ede0336 100644 --- a/BaS_gcc/sys/exceptions.S +++ b/BaS_gcc/sys/exceptions.S @@ -20,8 +20,6 @@ * Author: Markus Fröschle */ -#define DBG_EXC - #include "startcf.h" #if MACHINE_FIREBEE #include "firebee.h" @@ -48,25 +46,26 @@ .extern _irq7_handler /* Register read/write macros */ -#define MCF_MMU_MMUCR __MMUBAR -#define MCF_MMU_MMUOR __MMUBAR+0x04 -#define MCF_MMU_MMUSR __MMUBAR+0x08 -#define MCF_MMU_MMUAR __MMUBAR+0x10 -#define MCF_MMU_MMUTR __MMUBAR+0x14 -#define MCF_MMU_MMUDR __MMUBAR+0x18 +#define MCF_MMU_MMUCR __MMUBAR +#define MCF_MMU_MMUOR __MMUBAR+0x04 +#define MCF_MMU_MMUSR __MMUBAR+0x08 +#define MCF_MMU_MMUAR __MMUBAR+0x10 +#define MCF_MMU_MMUTR __MMUBAR+0x14 +#define MCF_MMU_MMUDR __MMUBAR+0x18 -#define MCF_EPORT_EPPAR __MBAR+0xF00 -#define MCF_EPORT_EPDDR __MBAR+0xF04 -#define MCF_EPORT_EPIER __MBAR+0xF05 -#define MCF_EPORT_EPDR __MBAR+0xF08 -#define MCF_EPORT_EPPDR __MBAR+0xF09 -#define MCF_EPORT_EPFR __MBAR+0xF0C +#define MCF_EPORT_EPPAR __MBAR+0xF00 +#define MCF_EPORT_EPDDR __MBAR+0xF04 +#define MCF_EPORT_EPIER __MBAR+0xF05 +#define MCF_EPORT_EPDR __MBAR+0xF08 +#define MCF_EPORT_EPPDR __MBAR+0xF09 +#define MCF_EPORT_EPFR __MBAR+0xF0C -#define MCF_GPIO_PODR_FEC1L __MBAR+0xA07 -#define MCF_PSC0_PSCTB_8BIT __MBAR+0x860C +#define MCF_GPIO_PODR_FEC1L __MBAR+0xA07 -#define MCF_PSC3_PSCRB_8BIT __MBAR+0x890C -#define MCF_PSC3_PSCTB_8BIT __MBAR+0x890C +#define MCF_PSC0_PSCTB_8BIT __MBAR+0x860C + +#define MCF_PSC3_PSCRB_8BIT __MBAR+0x890C +#define MCF_PSC3_PSCTB_8BIT __MBAR+0x890C .global _vec_init @@ -95,45 +94,44 @@ .equ INT_SOURCE_USB_DSPI_TCF,29 // transfer complete interrupt .equ INT_SOURCE_USB_DSPI_TFFF,30 // transfer FIFO fill interrupt .equ INT_SOURCE_USB_DSPI_EOQF,31 // end of queue interrupt - .equ INT_SOURCE_PSC3,32 // PSC3 interrupt - .equ INT_SOURCE_PSC2,33 // PSC2 interrupt - .equ INT_SOURCE_PSC1,34 // PSC1 interrupt - .equ INT_SOURCE_PSC0,35 // PSC0 interrupt + .equ INT_SOURCE_PSC3,32 // PSC3 interrupt + .equ INT_SOURCE_PSC2,33 // PSC2 interrupt + .equ INT_SOURCE_PSC1,34 // PSC1 interrupt + .equ INT_SOURCE_PSC0,35 // PSC0 interrupt .equ INT_SOURCE_CTIMERS,36 // combined source for comm timers - .equ INT_SOURCE_SEC,37 // SEC interrupt - .equ INT_SOURCE_FEC1,38 // FEC1 interrupt - .equ INT_SOURCE_FEC0,39 // FEC0 interrupt - .equ INT_SOURCE_I2C,40 // I2C interrupt + .equ INT_SOURCE_SEC,37 // SEC interrupt + .equ INT_SOURCE_FEC1,38 // FEC1 interrupt + .equ INT_SOURCE_FEC0,39 // FEC0 interrupt + .equ INT_SOURCE_I2C,40 // I2C interrupt .equ INT_SOURCE_PCIARB,41 // PCI arbiter interrupt - .equ INT_SOURCE_CBPCI,42 // COMM bus PCI interrupt + .equ INT_SOURCE_CBPCI,42 // COMM bus PCI interrupt .equ INT_SOURCE_XLBPCI,43 // XLB PCI interrupt .equ INT_SOURCE_XLBARB,47 // XLBARB to PCI interrupt - .equ INT_SOURCE_DMA,48 // multichannel DMA interrupt + .equ INT_SOURCE_DMA,48 // multichannel DMA interrupt .equ INT_SOURCE_CAN0_ERROR,49 // FlexCAN error interrupt .equ INT_SOURCE_CAN0_BUSOFF,50 // FlexCAN bus off interrupt .equ INT_SOURCE_CAN0_MBOR,51 // message buffer ORed interrupt - .equ INT_SOURCE_SLT1,53 // slice timer 1 interrupt - .equ INT_SOURCE_SLT0,54 // slice timer 0 interrupt + .equ INT_SOURCE_SLT1,53 // slice timer 1 interrupt + .equ INT_SOURCE_SLT0,54 // slice timer 0 interrupt .equ INT_SOURCE_CAN1_ERROR,55 // FlexCAN error interrupt .equ INT_SOURCE_CAN1_BUSOFF,56 // FlexCAN bus off interrupt .equ INT_SOURCE_CAN1_MBOR,57 // message buffer ORed interrupt - .equ INT_SOURCE_GPT3,59 // GPT3 timer interrupt - .equ INT_SOURCE_GPT2,60 // GPT2 timer interrupt - .equ INT_SOURCE_GPT1,61 // GPT1 timer interrupt - .equ INT_SOURCE_GPT0,62 // GPT0 timer interrupt + .equ INT_SOURCE_GPT3,59 // GPT3 timer interrupt + .equ INT_SOURCE_GPT2,60 // GPT2 timer interrupt + .equ INT_SOURCE_GPT1,61 // GPT1 timer interrupt + .equ INT_SOURCE_GPT0,62 // GPT0 timer interrupt // Atari register equates (provided by FPGA) .equ vbasehi, 0xffff8201 - -/* MMU register read/write macros */ - -#define MCF_MMU_MMUCR __MMUBAR -#define MCF_MMU_MMUOR __MMUBAR+0x04 -#define MCF_MMU_MMUSR __MMUBAR+0x08 -#define MCF_MMU_MMUAR __MMUBAR+0x10 -#define MCF_MMU_MMUTR __MMUBAR+0x14 -#define MCF_MMU_MMUDR __MMUBAR+0x18 +//mmu --------------------------------------------------- +/* Register read/write macros */ +#define MCF_MMU_MMUCR __MMUBAR +#define MCF_MMU_MMUOR __MMUBAR+0x04 +#define MCF_MMU_MMUSR __MMUBAR+0x08 +#define MCF_MMU_MMUAR __MMUBAR+0x10 +#define MCF_MMU_MMUTR __MMUBAR+0x14 +#define MCF_MMU_MMUDR __MMUBAR+0x18 /* Bit definitions and macros for MCF_MMU_MMUCR */ @@ -187,19 +185,35 @@ .equ MCD_TT_FLAGS_RL, 0x1 .equ MCD_TT_FLAGS_SP, 0x4 .equ DMA_ALWAYS, 0 +//--------------------------------------------------- +/********************************************************************* +* +* General Purpose Timers (GPT) +* +*********************************************************************/ /* Register read/write macros */ #define MCF_GPT0_GMS __MBAR+0x800 + +/********************************************************************* +* +* Slice Timers (SLT) +* +*********************************************************************/ + #define MCF_SLT0_SCNT __MBAR+0x908 +/**********************************************************/ +// macros +/**********************************************************/ .altmacro .macro irq vector,int_mask,clr_int move.w #0x2700,sr // disable interrupt subq.l #8,a7 movem.l d0/a5,(a7) // save registers - lea MCF_EPORT_EPFR,a5 - move.b #\clr_int,(a5) // clear int pending + lea MCF_EPORT_EPFR,a5 + move.b #\clr_int,(a5) // clear int pending movem.l (a7),d0/a5 // restore registers addq.l #8,a7 @@ -223,74 +237,73 @@ * If anybody knows of any better way on how to do this - please do! * */ - .macro mchar st,a,b,c,d,tgt - \st #\a << 24|\b<<16|\c<<8|\d,\tgt - .endm + .macro mchar st,a,b,c,d,tgt + \st #\a << 24|\b<<16|\c<<8|\d,\tgt + .endm - .text +.text _vec_init: - move.l a2,-(sp) // Backup registers - - mov3q.l #-1,_rt_mod // rt_mod auf super - clr.l _rt_ssp - clr.l _rt_usp - clr.l _rt_vbr - move.l #__RAMBAR0,d0 // exception vectors reside in rambar0 - movec d0,VBR - move.l d0,a0 - move.l a0,a2 + move.l a2,-(sp) // Backup registers + mov3q.l #-1,_rt_mod // rt_mod auf super + clr.l _rt_ssp + clr.l _rt_usp + clr.l _rt_vbr + move.l #__RAMBAR0,d0 // exception vectors reside in rambar0 + movec d0,VBR + move.l d0,a0 + move.l a0,a2 init_vec: move.l #256,d0 - lea std_exc_vec(pc),a1 // standard vector + lea std_exc_vec(pc),a1 // standard vector init_vec_loop: move.l a1,(a2)+ // set standard vector for all exceptions subq.l #1,d0 - bne init_vec_loop + bne init_vec_loop - move.l #__SUP_SP,(a0) // set initial stack pointer at start of exception vector table + move.l #__SUP_SP,(a0) // set initial stack pointer at start of exception vector table - lea reset_vector(pc),a1 // set reset vector + lea reset_vector(pc),a1 // set reset vector move.l a1,0x04(a0) - lea access_exception(pc),a1 // set illegal access exception handler + lea access(pc),a1 // set illegal access exception handler move.l a1,0x08(a0) - + .extern _get_bas_drivers // trap #0 (without any parameters for now) is used to provide BaS' driver addresses to the OS - lea _get_bas_drivers(pc),a1 - move.l a1,0x80(a0) // trap #0 exception vector + lea _get_bas_drivers(pc),a1 + move.l a1,0x80(a0) // trap #0 exception vector #ifdef MACHINE_FIREBEE // ACP interrupts 1-7 (user-defined, generated by FPGA on the FireBee, M5484LITE has irq7 and irq5 for PCI) - lea irq1(pc),a1 + lea irq1(pc),a1 move.l a1,0x104(a0) - lea irq2(pc),a1 + lea irq2(pc),a1 move.l a1,0x108(a0) - lea irq3(pc),a1 + lea irq3(pc),a1 move.l a1,0x10c(a0) - lea irq4(pc),a1 + lea irq4(pc),a1 move.l a1,0x110(a0) - lea irq5(pc),a1 + lea irq5(pc),a1 move.l a1,0x114(a0) - lea irq6(pc),a1 + lea irq6(pc),a1 move.l a1,0x118(a0) - lea irq7(pc),a1 + lea irq7(pc),a1 move.l a1,0x11c(a0) // install PSC vectors (used for PIC communication on the FireBee) - lea handler_psc3(pc),a1 + lea handler_psc3(pc),a1 // PSC3 interrupt source = 32 move.l a1,(INT_SOURCE_PSC3 + 64) * 4(a0) // timer vectors (triggers when vbashi gets changed, used for video page copy) - lea handler_gpt0(pc),a1 + lea handler_gpt0(pc),a1 // GPT0 interrupt source = 62 move.l a1,(INT_SOURCE_GPT0 + 64) * 4(a0) #endif /* MACHINE_FIREBEE */ // install lowlevel_isr_handler for the three GPT timers - lea _lowlevel_isr_handler(pc),a1 + lea _lowlevel_isr_handler(pc),a1 move.l a1,(INT_SOURCE_GPT1 + 64) * 4(a0) move.l a1,(INT_SOURCE_GPT2 + 64) * 4(a0) move.l a1,(INT_SOURCE_GPT3 + 64) * 4(a0) @@ -308,8 +321,6 @@ init_vec_loop: move.l (sp)+,a2 // Restore registers rts - - /* * exception vector routines */ @@ -324,8 +335,8 @@ std_exc_vec: #ifdef DBG_EXC // printout vector number of exception - lea -4 * 4(sp),sp // reserve stack space - movem.l d0-d1/a0-a1,(sp) // save gcc scratch registers + lea -4 * 4(sp),sp // reserve stack space + movem.l d0-d1/a0-a1,(sp) // save gcc scratch registers lsr.l #2,d0 // shift vector number in place cmp.l #33,d0 @@ -336,19 +347,19 @@ std_exc_vec: beq noprint cmp.l #46,d0 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() - pea exception_text - jsr _xprintf // call xprintf() + pea exception_text + jsr _xprintf // call xprintf() add.l #3*4,sp // adjust stack noprint: - - movem.l (sp),d0-d1/a0-a1 // restore registers - lea 4 * 4(sp),sp + + movem.l (sp),d0-d1/a0-a1 // restore registers + lea 4 * 4(sp),sp #endif /* DBG_EXC */ add.l _rt_vbr,d0 // + VBR - move.l d0,a5 + move.l d0,a5 move.l (a5),d0 // fetch exception routine address move.l 4(sp),a5 // restore a5 @@ -358,7 +369,7 @@ noprint: bset #13,d0 // set supervisor bit move.w d0,sr // move.l (a7)+,d0 // restore d0 - rts // jump to exception routine + rts // jump to exception routine exception_text: .ascii "DEBUG: EXCEPTION %d caught at %p" @@ -369,168 +380,173 @@ reset_vector: move.w #0x2700,sr // disable interrupt move.l #0x31415926,d0 cmp.l 0x426,d0 // _resvalid: reset vector valid? - beq std_exc_vec // yes-> - jmp _rom_entry // no, cold start machine + beq std_exc_vec // yes-> + jmp _rom_entry // no, cold start machine -// -// Triggered when code tries to access a memory area that is not known to the MMU yet. -// This is either a "classic" bus error or the MMU hit a "legal" page not yet mapped. -// -access_exception: - move.w #0x2700,sr // avoid us being interrupted by the video handler - // (this would probably overwrite the MMUAR register) +access: + move.w #0x2700,sr // disable interrupt + move.l d0,-(sp) // ++ vr - // save gcc scratch registers, others will be handled by called function - lea -4*4(sp),sp - movem.l d0-d1/a0-a1,(sp) + move.w 4(sp),d0 // get format_status word from stack + andi.l #0x0c03,d0 // mask out fault status bits + cmpi.l #0x0401,d0 // TLB miss on opword of instruction fetch? + beq access_mmu // yes + cmpi.l #0x0402,d0 // TLB miss on extension word of instruction fetch? + beq access_mmu // yes + cmpi.l #0x0802,d0 // TLB miss on data write? + beq access_mmu // yes + cmpi.l #0x0c02,d0 // TLB miss on data read, or read-modify-write? + beq access_mmu // yes + bra bus_error // everything else is a classic bus error - lea 4*4(sp),a0 // original stack pointer +access_mmu: + move.l MCF_MMU_MMUSR,d0 // did the last fault hit in TLB? + btst #1,d0 // yes, it did. So we already mapped that page + bne bus_error // and this must be a real bus error - move.l (a0),-(sp) // format status word - move.l 4(a0),-(sp) // program counter at access error + move.l MCF_MMU_MMUAR,d0 + cmp.l #__FASTRAM_END,d0 // above max User RAM area? + bge bus_error // -> bus error - jsr _access_exception // note the underscore - lea 2*4(sp),sp // adjust stack + lea -5*4(sp),sp // save gcc scratch registers + movem.l d0-d1/a0-a2,(sp) - tst.l d0 // handled? + move.l d0,-(sp) // fault address + jsr _mmutr_miss // else we have an MMU TLB miss + addq.l #4,sp - movem.l (sp),d0-d1/a0-a1 // restore scratch registers - lea 4*4(sp),sp + movem.l (sp),d0-d1/a0-a2 // restore gcc scratch registers + lea 5*4(sp),sp - beq bus_error // no + move.l (sp)+,d0 // restore register rte bus_error: - bra std_exc_vec - + move.l (sp)+,d0 // restore register + bra std_exc_vec + zero_divide: + move.w #0x2700,sr // disable interrupt move.l a0,-(a7) move.l d0,-(a7) move.l 12(a7),a0 // pc move.w (a0)+,d0 // command word btst #7,d0 // long? - beq zd_word // nein-> + beq zd_word // nein-> addq.l #2,a0 zd_word: and.l 0x3f,d0 // mask out ea field cmp.w #0x08,d0 // -(ax) or less? - ble zd_end + ble zd_end addq.l #2,a0 cmp.w #0x39,d0 // xxx.L - bne zd_nal + bne zd_nal addq.l #2,a0 - bra zd_end + bra zd_end -zd_nal: cmp.w #0x3c,d0 // immediate? - bne zd_end // no-> +zd_nal: cmp.w #0x3c,d0 // immediate? + bne zd_end // no-> btst #7,d0 // long? - beq zd_end // no + beq zd_end // no addq.l #2,a0 zd_end: move.l a0,12(a7) move.l (a7)+,d0 - move.l (a7)+,a0 + move.l (a7)+,a0 rte + +#ifdef _NOT_USED_ +linea: + move.w #0x2700,sr // disable interrupt + halt + nop + nop +linef: + move.w #0x2700,sr // disable interrupt + halt + nop + nop +format: + move.w #0x2700,sr // disable interrupt + halt + nop + nop + +//floating point +flpoow: + move.w #0x2700,sr // disable interrupt + halt + nop + nop +#endif /* _NOT_USED */ irq1: - irq 0x64,1,0x02 + irq 0x64,1,0x02 -irq2: // hbl - // move.b #3,2(a7) - // rte - irq 0x68,2,0x04 +irq2: // hbl + // move.b #3,2(a7) + // rte + irq 0x68,2,0x04 irq3: - irq 0x6c,3,0x08 + irq 0x6c,3,0x08 -irq4: // vbl - irq 0x70,4,0x10 +irq4: // vbl + irq 0x70,4,0x10 -#if MACHINE_M5484LITE // handlers for M5484LITE +#if MACHINE_M5484LITE_notyet // handlers for M5484LITE -irq5: // irq5 is tied to PCI INTC# and PCI INTD# on the M5484LITE +irq5: // irq5 is tied to PCI INTC# and PCI INTD# on the M5484LITE 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) - jsr _irq5_handler // call C handler routine + jsr _irq5_handler // call C handler routine - movem.l (sp),d0-d1/a0-a1 // restore registers - lea 4*4(sp),sp + movem.l (sp),d0-d1/a0-a1 // restore registers + lea 4*4(sp),sp - rte // return from exception + rte // return from exception irq5text: .ascii "IRQ5!" .dc.b 13,10,0 -irq6: - irq 0x74,5,0x20 +irq6: + 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 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) - jsr _irq7_handler // call C handler routine + jsr _irq7_handler // call C handler routine - movem.l (sp),d0-d1/a0-a1 // restore registers - lea 4*4(sp),sp + movem.l (sp),d0-d1/a0-a1 // restore registers + lea 4*4(sp),sp - rte // return from exception + rte // return from exception irq7text: .ascii "IRQ7!" .dc.b 13,10,0 -#elif MACHINE_FIREBEE /* these handlers are only meaningful for the Firebee */ -irq5: - irq 0x74,5,0x20 - - .extern _irq6_interrupt_handler // highlevel C handler +#elif MACHINE_FIREBEE /* these handlers are only meaningful for the Firebee */ +irq5: // irq5 is tied to PCI INTC# and PCI INTD# on the M5484LITE + irq 0x74,5,0x20 irq6: // MFP interrupt from FPGA - move.w #0x2700,sr // disable interrupts - - lea -4 * 4(sp),sp // save gcc scratch registers - movem.l d0-d1/a0-a1,(sp) - - move.l 4 * 4(sp),-(sp) // push original exception stack frame - move.l 5 * 4(sp),-(sp) - jsr _irq6_interrupt_handler // call highlevel C handler - lea.l 2 * 4(sp),sp - - tst.l d0 // completely handled? - - movem.l (sp),d0-d1/a0-a1 // restore registers saved above - lea 4 * 4(sp),sp // adjust stack - - beq irq6_os // call OS handler - rte - -irq6_os: // call native OS irq6 handler - move.l a5,-(sp) // save registers: TODO: this could be done more effective - move.l d0,-(sp) - move.l 0xf0020000,a5 // fetch vector - add.l _rt_vbr,a5 // add vector base - move.l (a5),d0 // fetch handler - move.l 4(sp),a5 // restore a5 - move.l d0,4(sp) // prepare indirect return - move.l (sp)+,d0 // restore d0 - move.w #0x2600,sr // set interrupt mask - rts - -#ifdef _NOT_USED_ /* functionality moved to _irq6_interrupt_handler() (C) */ + move.w #0x2700,sr // disable interrupt subq.l #8,a7 movem.l d0/a5,(a7) // save registers - lea MCF_EPORT_EPFR,a5 // clear int6 from edge port + lea MCF_EPORT_EPFR,a5 // clear int6 from edge port bset #6,(a5) // there was a potential bug here before: would also clear all other edge port interrupts that might have happened... @@ -538,48 +554,48 @@ irq6_os: // call native OS irq6 handler // screen adr change timed out? move.l _video_sbt,d0 - beq irq6_non_sca // nothing to do if 0 - sub.l #0x70000000,d0 // substract 14 seconds - lea MCF_SLT0_SCNT,a5 - cmp.l (a5),d0 // time reached? - ble irq6_non_sca // not yet + beq irq6_non_sca // nothing to do if 0 + sub.l #0x70000000,d0 // substract 14 seconds + lea MCF_SLT0_SCNT,a5 + cmp.l (a5),d0 // time reached? + ble irq6_non_sca // not yet - lea -28(a7),a7 // save more registers - movem.l d0-d4/a0-a1,(a7) // - clr.l d3 // beginn mit 0 - jsr _flush_and_invalidate_caches + lea -28(a7),a7 // save more registers + movem.l d0-d4/a0-a1,(a7) // + clr.l d3 // beginn mit 0 + jsr _flush_and_invalidate_caches // eintrag suchen irq6_next_sca: - move.l d3,d0 - move.l d0,MCF_MMU_MMUAR // addresse - move.l #0x106,d4 - move.l d4,MCF_MMU_MMUOR // suchen -> - nop - move.l MCF_MMU_MMUOR,d4 - clr.w d4 - swap d4 - move.l d4,MCF_MMU_MMUAR + move.l d3,d0 + move.l d0,MCF_MMU_MMUAR // addresse + move.l #0x106,d4 + move.l d4,MCF_MMU_MMUOR // suchen -> + nop + move.l MCF_MMU_MMUOR,d4 + clr.w d4 + swap d4 + move.l d4,MCF_MMU_MMUAR mvz.w #0x10e,d4 - move.l d4,MCF_MMU_MMUOR // einträge holen aus mmu - nop - move.l MCF_MMU_MMUTR,d4 // ID holen - lsr.l #2,d4 // bit 9 bis 2 - cmp.w #sca_page_ID,d4 // ist screen change ID? - bne irq6_sca_pn // nein -> page keine screen area next + move.l d4,MCF_MMU_MMUOR // einträge holen aus mmu + nop + move.l MCF_MMU_MMUTR,d4 // ID holen + lsr.l #2,d4 // bit 9 bis 2 + cmp.w #sca_page_ID,d4 // ist screen change ID? + bne irq6_sca_pn // nein -> page keine screen area next // eintrag �ndern add.l #std_mmutr,d0 move.l d3,d1 // page 0? - beq irq6_sca_pn0 // ja -> - add.l #copyback_mmudr,d1 // sonst page cb - bra irq6_sca_pn1c + beq irq6_sca_pn0 // ja -> + add.l #copyback_mmudr,d1 // sonst page cb + bra irq6_sca_pn1c irq6_sca_pn0: add.l #writethrough_mmudr|MCF_MMU_MMUDR_LK,d1 // page wt and locked irq6_sca_pn1c: - mvz.w #0x10b,d2 // MMU update - move.l d0,MCF_MMU_MMUTR + mvz.w #0x10b,d2 // MMU update + move.l d0,MCF_MMU_MMUTR 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 // page copy move.l d3,a0 @@ -587,59 +603,131 @@ irq6_sca_pn1c: move.l d3,a1 move.l #0x10000,d4 // one whole page (1 MB) +#define _DO_CPU_COPY +#ifndef _DO_CPU_COPY + + // experiment: do video page copy using Coldfire DMA + + lea -15 * 4(sp),sp + movem.l d0-d1/a0-a1,(sp) // save gcc scratch registers + clr.l -(sp) // no special functions + move.l #MCD_SINGLE_DMA|MCD_TT_FLAGS_CW|MCD_TT_FLAGS_RL|MCD_TT_FLAGS_SP,-(sp) + mov3q #7,-(sp) // highest DMA priority + move.l #DMA_ALWAYS,-(sp) // do memory to memory DMA + move.l #1,-(sp) // copy 4 bytes at a time + move.l #0x100000,-(sp) // copy 1 Megabyte + move.l #4,-(sp) // destination increment + move.l a1,-(sp) // destination adress + move.l #4,-(sp) // source increment + move.l a0,-(sp) // source adress + move.l #1,-(sp) // channel 1 + jsr _MCD_startDma + + movem.l (sp),d0-d1/a0-a1 // restore gcc scratch registers + lea 15 * 4(sp),sp // adjust stack + +wait_dma_finished: + clr.l -(sp) + jsr _MCD_dmaStatus + addq.l #4,sp + tst.l d0 + cmp.l #6,d0 + bne wait_dma_finished +#else +irq6_vcd0_loop: + move.l (a0)+,(a1)+ // page copy + move.l (a0)+,(a1)+ + move.l (a0)+,(a1)+ + move.l (a0)+,(a1)+ + subq.l #1,d4 + bne irq6_vcd0_loop +#endif /* _DO_CPU_COPY */ + irq6_sca_pn: - add.l #0x00100000,d3 // next - cmp.l #0x00d00000,d3 // ende? + add.l #0x00100000,d3 // next + cmp.l #0x00d00000,d3 // ende? blt irq6_next_sca // nein-> move.l #0x2000,d0 - move.l d0,_video_tlb // anfangszustand wieder herstellen - clr.l _video_sbt // zeit löschen + move.l d0,_video_tlb // anfangszustand wieder herstellen + clr.l _video_sbt // zeit löschen - movem.l (sp),d0-d4/a0-a1 // restore registers - lea 7 * 4(sp),sp + movem.l (sp),d0-d4/a0-a1 // restore registers + lea 7 * 4(sp),sp irq6_non_sca: // test auf acsi dma ----------------------------------------------------------------- - lea 0xfffffa0b,a5 - bset #7,-4(a5) // int ena - btst.b #7,(a5) // acsi dma int? - beq non_acsi_dma - bsr acsi_dma + lea 0xfffffa0b,a5 + bset #7,-4(a5) // int ena + btst.b #7,(a5) // acsi dma int? + beq non_acsi_dma + bsr acsi_dma non_acsi_dma: // ---------------------------------------------------------------------------------- tst.b (a5) - bne irq6_1 + bne irq6_1 tst.b 2(a5) - bne irq6_1 + bne irq6_1 movem.l (a7),d0/a5 addq.l #8,a7 - rte + rte irq6_1: - lea MCF_GPIO_PODR_FEC1L,a5 + lea MCF_GPIO_PODR_FEC1L,a5 bclr.b #4,(a5) // led on - lea blinker,a5 + lea blinker,a5 addq.l #1,(a5) // +1 move.l (a5),d0 and.l #0x80,d0 - bne irq6_2 - lea MCF_GPIO_PODR_FEC1L,a5 + bne irq6_2 + lea MCF_GPIO_PODR_FEC1L,a5 bset.b #4,(a5) // led off irq6_2: - move.l 0xf0020000,a5 // vector holen - add.l _rt_vbr,a5 // basis - move.l (a5),d0 // vector holen - move.l 4(a7),a5 // a5 zurück - move.l d0,4(a7) // vector eintragen - move.l (a7)+,d0 // d0 zurück +// test auf protect mode --------------------- + move.b DIP_SWITCHa,d0 + btst #7,d0 + bne irq6_3 // ja-> +// ------------------------------------------- + move.l 0xF0020000,a5 // vector holen + add.l _rt_vbr,a5 // basis + move.l (a5),d0 // vector holen + move.l 4(a7),a5 // a5 zurück + move.l d0,4(a7) // vector eintragen + move.l (a7)+,d0 // d0 zurück move #0x2600,sr rts +irq6_3: + move.l usp,a5 // usp holen + tst.b _rt_mod // supervisor? + bne sev_sup6 // ja -> + mov3q.l #-1,_rt_mod // auf supervisor setzen + move.l a5,_rt_usp // rt_usp speichern + move.l _rt_ssp,a5 // rt_ssp holen + move.l 12(a7),-(a5) // pc transferieren + move.l 8(a7),-(a5) // sr transferieren + move.l a5,usp // usp setzen + move.l 0xF0020000,a5 // vector holen: intack routine + add.l _rt_vbr,a5 // virtuelle VBR des Systems + move.l (a5),12(a7) // hier gehts weiter + movem.l (a7),d0/a5 // register zurück + addq.l #8,a7 + move.b #6,2(a7) // intmaske setzen + rte // und weg +sev_sup6: + move.l 12(a7),-(a5) // pc transferieren + move.l 8(a7),-(a5) // sr,vec + bset #5,2(a5) // auf super setzen + move.l a5,usp // usp setzen + move.l 0xF0020000,a5 // vector holen: intack routine + add.l _rt_vbr,a5 // virtuelle VBR des Systems + move.l (a5),12(a7) // hier gehts weiter + movem.l (a7),d0/a5 // register zurück + rts .data blinker:.long 0 - .text + .text /* * pseudo dma @@ -647,7 +735,7 @@ blinker:.long 0 acsi_dma: // atari dma move.l a1,-(a7) move.l d1,-(a7) - + lea MCF_PSC0_PSCTB_8BIT,a1 // ++ vr mchar move.l, 'D,'M','A,'\ ,(a1) //move.l #"DMA ",(a1) @@ -658,33 +746,33 @@ acsi_dma: // atari dma acsi_dma_start: move.l -12(a5),a1 // dma adresse move.l -8(a5),d0 // byt counter - ble acsi_dma_end - btst.b #0,-16(a5) // write? (dma modus reg) + ble acsi_dma_end + btst.b #0,-16(a5) // write? (dma modus reg) bne acsi_dma_wl // ja-> acsi_dma_rl: - tst.b -4(a5) // dma req? - 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 + tst.b -4(a5) // dma req? + 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 + + moveq #'.',d1 + move.b d1,MCF_PSC0_PSCTB_8BIT - moveq #'.',d1 - move.b d1,MCF_PSC0_PSCTB_8BIT - - sub.l #16,d0 // byt counter -16 - bpl acsi_dma_rl - bra acsi_dma_finished + sub.l #16,d0 // byt counter -16 + bpl acsi_dma_rl + bra acsi_dma_finished acsi_dma_wl: - tst.b -4(a5) // dma req? - 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 - - moveq #'.',d1 - move.b d1,MCF_PSC0_PSCTB_8BIT + tst.b -4(a5) // dma req? + 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 + + moveq #'.',d1 + move.b d1,MCF_PSC0_PSCTB_8BIT sub.l #16,d0 // byt counter -16 bpl acsi_dma_wl @@ -692,29 +780,26 @@ acsi_dma_finished: move.l a1,-12(a5) // adresse zur�ck move.l d0,-8(a5) // byt counter zur�ck acsi_dma_end: - tst.b -4(a5) // dma req? - bmi acsi_dma_start // ja-> - lea 0xfffffa0b,a5 - bclr.b #7,4(a5) // clear int in service mfp - bclr.b #7,(a5) // clear int pending mfp 0xfffffa0b - + tst.b -4(a5) // dma req? + bmi acsi_dma_start // ja-> + lea 0xfffffa0b,a5 + bclr.b #7,4(a5) // clear int in service mfp + bclr.b #7,(a5) // clear int pending mfp 0xfffffa0b + move.w #0x0d0a,d1 move.w d1,MCF_PSC0_PSCTB_8BIT - + move.l (a7)+,d1 move.l (a7)+,a1 rts - -#endif /* _NOT_USED_ */ - /* * irq 7 = pseudo bus error */ irq7: - lea -12(sp),sp + lea -12(sp),sp movem.l d0/a0,(sp) - move.l __RAMBAR0+0x008,a0 // real access error handler + move.l __RAMBAR0+0x008,a0 // real access error handler move.l a0,8(sp) // this will be the return address for rts move.w 12(sp),d0 // format/vector word @@ -736,58 +821,77 @@ irq7: * psc3 com PIC MCF */ handler_psc3: - .extern _pic_interrupt_handler + move.w #0x2700,sr // disable interrupt + lea -20(a7),a7 + movem.l d0-d2/a0/a3,(a7) + lea MCF_PSC3_PSCRB_8BIT,a3 + move.b (a3),d1 + cmp.b #2,d1 // anforderung rtc daten? + bne psc3_fertig - move.w #0x2700,sr // disable interrupt - lea -4 * 4(sp),sp // save gcc scratch registers - movem.l d0-d1/a0-a1,(sp) + lea MCF_PSC0_PSCTB_8BIT,a0 // ++ vr + mchar move.l,'\P,'\I,'C,' ,(a0) + mchar move.l,'I,'N,'T,'\ ,(a0) + mchar move.l,'R,'T,'C,'!,(a0) + mchar move.l,0x0d,0x0a,0,0,(a0) - jsr _pic_interrupt_handler // call high level interrupt handler - - movem.l (sp),d0-d1/a0-a1 // restore registers - rte + lea 0xffff8961,a0 + lea MCF_PSC3_PSCTB_8BIT,a3 + clr.l d1 + moveq #64,d2 + move.b #0x82,(a3) // header: rtcd mcf->pic +loop_sr2: + move.b d1,(a0) + move.b 2(a0),d0 + move.b d0,(a3) + addq.l #1,d1 + cmp.b d1,d2 + bne loop_sr2 +psc3_fertig: + movem.l (a7),d0-d2/a0/a3 // restore saved registers + lea 20(a7),a7 + RTE /* * general purpose timer 0 (GPT0): video change, later also others. GPT0 is used as - * input trigger. It is connected to the TIN0 signal of the FPGA which triggers it everytime + * input trigger. It is connected to the TIN0 signal of the FPGA and triggers everytime * vbasehi is written to, i.e. when the video base address gets changed */ handler_gpt0: - 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) - mvz.b vbasehi,d0 // screen base address high - cmp.w #2,d0 // screen base lower than 0x20000? - blt video_chg_end // yes, do nothing - cmp.w #0xd0,d0 // lower than 0xd00000? - normal Falcon video area, mapped - // to 60d00000 (FPGA video memory) - blt sca_other + mvz.b vbasehi,d0 // screen base address high + cmp.w #2,d0 // screen base lower than 0x20000? + blt video_chg_end // yes, do nothing + cmp.w #0xd0,d0 // lower than 0xd00000? - normal Falcon video area, mapped + // to 60d00000 (FPGA video memory) + blt sca_other // - lea MCF_SLT0_SCNT,a0 - move.l (a0),_video_sbt // save time + lea MCF_SLT0_SCNT,a0 + move.l (a0),_video_sbt // save time - bra video_chg_end // FIXME: don't we need to get out here? sca_other: - lsl.l #8,d0 // build new screen start address from Atari register contents - move.b 0xffff8203,d0 // mid byte + lsl.l #8,d0 // build new screen start address from Atari register contents + move.b 0xffff8203,d0 // mid byte lsl.l #8,d0 - move.b 0xffff820d,d0 // low byte + move.b 0xffff820d,d0 // low byte move.l d0,d3 video_chg_1page: // check if page is already marked as video page moveq #20,d4 move.l d0,d2 - lsr.l d4,d2 // new page + lsr.l d4,d2 // new page move.l _video_tlb,d4 - bset.l d2,d4 // set as changed - bne video_chg_2page // was it set already? + bset.l d2,d4 // set as changed + bne video_chg_2page // was it set already? move.l d4,_video_tlb - jsr _flush_and_invalidate_caches + jsr _flush_and_invalidate_caches video_copy_data: move.l d4,_video_tlb @@ -795,59 +899,91 @@ video_copy_data: move.l d0,a0 move.l a0,a1 add.l #0x60000000,a1 - move.l #0x10000,d4 // whole page + move.l #0x10000,d4 // whole page +#ifndef _DO_CPU_COPY + + // experiment: do video page copy using Coldfire DMA + + lea -15 * 4(sp),sp + movem.l d0-d1/a0-a1,(sp) // save gcc scratch registers + + clr.l -(sp) // no special functions + move.l #MCD_SINGLE_DMA|MCD_TT_FLAGS_CW|MCD_TT_FLAGS_RL|MCD_TT_FLAGS_SP,-(sp) + mov3q #7,-(sp) // highest DMA priority + move.l #DMA_ALWAYS,-(sp) // do memory to memory DMA + move.l #1,-(sp) // copy 4 bytes at a time + move.l #0x100000,-(sp) // copy 1 Megabyte + move.l #4,-(sp) // destination increment + move.l a1,-(sp) // destination adress + move.l #4,-(sp) // source increment + move.l a0,-(sp) // source adress + move.l #1,-(sp) // channel 1 + jsr _MCD_startDma + +.wait_dma_finished: + clr.l -(sp) + jsr _MCD_dmaStatus + addq.l #4,sp + tst.l d0 + cmp.l #6,d0 + bne .wait_dma_finished + + movem.l (sp),d0-d1/a0-a1 // restore gcc scratch registers + lea 15 * 4(sp),sp // adjust stack + +#else video_copy_data_loop: - move.l (a0)+,(a1)+ // copy video page contents to real screen + move.l (a0)+,(a1)+ // copy video page contents to real screen move.l (a0)+,(a1)+ move.l (a0)+,(a1)+ move.l (a0)+,(a1)+ subq.l #1,d4 - bne video_copy_data_loop + bne video_copy_data_loop +#endif // eintrag suchen - move.l d0,MCF_MMU_MMUAR // adress - move.l #0x106,d4 - move.l d4,MCF_MMU_MMUOR // search -> new one will be offered if not found - nop - move.l MCF_MMU_MMUOR,d4 - clr.w d4 - swap d4 - move.l d4,MCF_MMU_MMUAR + move.l d0,MCF_MMU_MMUAR // adress + move.l #0x106,d4 + move.l d4,MCF_MMU_MMUOR // search -> new one will be offered if not found + nop + move.l MCF_MMU_MMUOR,d4 + clr.w d4 + swap d4 + move.l d4,MCF_MMU_MMUAR move.l d0,d1 add.l #MCF_MMU_MMUTR_ID(sca_page_ID)|std_mmutr,d0 add.l #0x60000000|writethrough_mmudr|MCF_MMU_MMUDR_LK,d1 - mvz.w #0x10b,d2 // MMU update - move.l d0,MCF_MMU_MMUTR + mvz.w #0x10b,d2 // MMU update + move.l d0,MCF_MMU_MMUTR 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 - video_chg_2page: // test of adjacent page is needed also move.l d3,d0 - mvz.w 0xffff8210,d4 // byts pro zeile - mvz.w 0xffff82aa,d2 // zeilen ende - mvz.w 0xffff82a8,d1 // zeilenstart - sub.l d1,d2 // differenz = anzahl zeilen - mulu d2,d4 // maximal 480 zeilen - add.l d4,d0 // video gr�sse - cmp.l #__STRAM_END,d0 // maximale addresse - bge video_chg_end // wenn gleich oder gr�sser -> fertig + mvz.w 0xffff8210,d4 // byts pro zeile + mvz.w 0xffff82aa,d2 // zeilen ende + mvz.w 0xffff82a8,d1 // zeilenstart + sub.l d1,d2 // differenz = anzahl zeilen + mulu d2,d4 // maximal 480 zeilen + add.l d4,d0 // video gr�sse + cmp.l #__STRAM_END,d0 // maximale addresse + bge video_chg_end // wenn gleich oder gr�sser -> fertig moveq #20,d4 move.l d0,d2 - lsr.l d4,d2 // neue page + lsr.l d4,d2 // neue page move.l _video_tlb,d4 - bset.l d2,d4 // setzen als ge�ndert - beq video_copy_data // nein nochmal + bset.l d2,d4 // setzen als ge�ndert + beq video_copy_data // nein nochmal video_chg_end: - lea MCF_GPT0_GMS,a0 // clear interrupt + lea MCF_GPT0_GMS,a0 // clear interrupt bclr.b #0,3(a0) nop bset.b #0,3(a0) - movem.l (a7),d0-d4/a0-a1 // restore saved registers - lea 7 * 4(sp),a7 + movem.l (a7),d0-d4/a0-a1 // restore saved registers + lea 7 * 4(sp),a7 rte #endif /* MACHINE_FIREBEE */ @@ -855,20 +991,20 @@ video_chg_end: * low-level interrupt service routine for routines registered with * isr_register_handler() */ - .global _lowlevel_isr_handler + .global _lowlevel_isr_handler .extern _isr_execute_handler _lowlevel_isr_handler: - move.w #0x2700,sr // disable interrupts - link a6,#-4*4 // make room for - movem.l d0-d1/a0-a1,(sp) // gcc scratch registers and save them + move.w #0x2700,sr // disable interrupts + link a6,#-4*4 // make room for + movem.l d0-d1/a0-a1,(sp) // gcc scratch registers and save them - move.w 4(a6),d0 // fetch vector number from stack - lsr.l #2,d0 // move it in place - andi.l #0x000000ff,d0 // mask it out - move.l d0,-(sp) // push it - jsr _isr_execute_handler // call the C handler - lea 4(sp),sp // adjust stack - movem.l (sp),d0-d1/a0-a1 // restore registers + move.w 4(a6),d0 // fetch vector number from stack + lsr.l #2,d0 // move it in place + andi.l #0x000000ff,d0 // mask it out + move.l d0,-(sp) // push it + jsr _isr_execute_handler // call the C handler + lea 4(sp),sp // adjust stack + movem.l (sp),d0-d1/a0-a1 // restore registers unlk a6 // cleanup stack rte diff --git a/BaS_gcc/sys/mmu.c b/BaS_gcc/sys/mmu.c index c0f0ec1..c742151 100644 --- a/BaS_gcc/sys/mmu.c +++ b/BaS_gcc/sys/mmu.c @@ -24,6 +24,26 @@ * Copyright 2013 M. Froeschle */ +#define ACR_BA(x) ((x) & 0xffff0000) +#define ACR_ADMSK(x) (((x) & 0xffff) << 16) +#define ACR_E(x) (((x) & 1) << 15) + +#define ACR_S(x) (((x) & 3) << 13) +#define ACR_S_USERMODE 0 +#define ACR_S_SUPERVISOR_MODE 1 +#define ACR_S_ALL 2 + +#define ACR_AMM(x) (((x) & 1) << 10) + +#define ACR_CM(x) (((x) & 3) << 5) +#define ACR_CM_CACHEABLE_WT 0x0 +#define ACR_CM_CACHEABLE_CB 0x1 +#define ACR_CM_CACHE_INH_PRECISE 0x2 +#define ACR_CM_CACHE_INH_IMPRECISE 0x3 + +#define ACR_SP(x) (((x) & 1) << 3) +#define ACR_W(x) (((x) & 1) << 2) + #include #include "bas_printf.h" #include "bas_types.h" @@ -42,12 +62,12 @@ #error "unknown machine!" #endif /* MACHINE_FIREBEE */ -#define DBG_MMU -#ifdef DBG_MMU -#define dbg(format, arg...) do { xprintf("DEBUG %s(): " format, __FUNCTION__, ##arg);} while(0) +//#define DEBUG_MMU +#ifdef DEBUG_MMU +#define dbg(format, arg...) do { xprintf("DEBUG: " format, ##arg);} while(0) #else #define dbg(format, arg...) do {;} while (0) -#endif /* DBG_MMU */ +#endif /* DEBUG_MMU */ /* * set ASID register @@ -59,11 +79,11 @@ inline uint32_t set_asid(uint32_t value) uint32_t ret = rt_asid; __asm__ __volatile__( - "movec %[value],ASID\n\t" - : /* no output */ - : [value] "r" (value) - : - ); + "movec %[value],ASID\n\t" + : /* no output */ + : [value] "r" (value) + : + ); rt_asid = value; @@ -81,11 +101,11 @@ inline uint32_t set_acr0(uint32_t value) uint32_t ret = rt_acr0; __asm__ __volatile__( - "movec %[value],ACR0\n\t" - : /* not output */ - : [value] "r" (value) - : - ); + "movec %[value],ACR0\n\t" + : /* not output */ + : [value] "r" (value) + : + ); rt_acr0 = value; return ret; @@ -101,11 +121,11 @@ inline uint32_t set_acr1(uint32_t value) uint32_t ret = rt_acr1; __asm__ __volatile__( - "movec %[value],ACR1\n\t" - : /* not output */ - : [value] "r" (value) - : - ); + "movec %[value],ACR1\n\t" + : /* not output */ + : [value] "r" (value) + : + ); rt_acr1 = value; return ret; @@ -122,11 +142,11 @@ inline uint32_t set_acr2(uint32_t value) uint32_t ret = rt_acr2; __asm__ __volatile__( - "movec %[value],ACR2\n\t" - : /* not output */ - : [value] "r" (value) - : - ); + "movec %[value],ACR2\n\t" + : /* not output */ + : [value] "r" (value) + : + ); rt_acr2 = value; return ret; @@ -142,11 +162,11 @@ inline uint32_t set_acr3(uint32_t value) uint32_t ret = rt_acr3; __asm__ __volatile__( - "movec %[value],ACR3\n\t" - : /* not output */ - : [value] "r" (value) - : - ); + "movec %[value],ACR3\n\t" + : /* not output */ + : [value] "r" (value) + : + ); rt_acr3 = value; return ret; @@ -158,417 +178,276 @@ inline uint32_t set_mmubar(uint32_t value) uint32_t ret = rt_mmubar; __asm__ __volatile__( - "movec %[value],MMUBAR\n\t" - : /* no output */ - : [value] "r" (value) - : /* no clobber */ - ); + "movec %[value],MMUBAR\n\t" + : /* no output */ + : [value] "r" (value) + : /* no clobber */ + ); rt_mmubar = value; NOP(); return ret; } - - -/* - * TODO: this would be nicer in an include file - */ -extern uint8_t _SYS_SRAM[]; -#define SYS_SRAM_ADDRESS ((uint32_t) &_SYS_SRAM[0]) -extern uint8_t _SYS_SRAM_SIZE[]; -extern uint8_t _FASTRAM_END[]; -extern uint32_t _TOS; - -struct mmu_mapping -{ - uint32_t phys; - uint32_t virt; - uint32_t length; - uint32_t pagesize; - struct map_flags flags; -}; - -static struct mmu_mapping locked_map[] = -{ - { - /* first Megabyte of physical memory */ - 0x0, /* physical address */ - 0x0, /* virtual address */ - 0x100000, /* 1 MByte */ - MMU_PAGE_SIZE_1M, - { CACHE_COPYBACK, SV_USER, 0, ACCESS_READ | ACCESS_WRITE | ACCESS_EXECUTE }, - }, - { - /* Falcon video memory. Needs special care */ - 0x60d00000, - 0xd00000, - 0x100000, - MMU_PAGE_SIZE_1M, - { CACHE_WRITETHROUGH, SV_USER, SCA_PAGE_ID, ACCESS_READ | ACCESS_WRITE | ACCESS_EXECUTE }, - }, - { - /* TOS in RAM */ - (uint32_t) &_TOS, - (uint32_t) &_TOS, - 0x100000, - MMU_PAGE_SIZE_1M, - { CACHE_COPYBACK, SV_USER, 0, ACCESS_READ | ACCESS_EXECUTE }, - }, - { - /* Firebee I/O area */ - 0xfff00000, - 0x00f00000, - 0x100000, - MMU_PAGE_SIZE_1M, - { CACHE_NOCACHE_PRECISE, SV_USER, 0, ACCESS_READ | ACCESS_WRITE }, - }, - { - /* BaS in RAM */ - SDRAM_START + SDRAM_SIZE - 0x00200000, - SDRAM_START + SDRAM_SIZE - 0x00200000, - 0x100000, - MMU_PAGE_SIZE_1M, - { CACHE_WRITETHROUGH, SV_PROTECT, 0, ACCESS_READ | ACCESS_WRITE | ACCESS_EXECUTE }, - }, - { - /* driver memory */ - SDRAM_START + SDRAM_SIZE - 0x00100000, - SDRAM_START + SDRAM_SIZE - 0x00100000, - 0x100000, - MMU_PAGE_SIZE_1M, - { CACHE_NOCACHE_PRECISE, SV_PROTECT, ACCESS_READ | ACCESS_WRITE | ACCESS_EXECUTE }, - }, -}; - -static int num_locked_mmu_maps = sizeof(locked_map) / sizeof(struct mmu_mapping); - -static struct mmu_mapping memory_map[] = -{ - /* map OS system vectors supervisor-protected */ - { - 0, - 0, - 0x800, - MMU_PAGE_SIZE_1K, - { CACHE_WRITETHROUGH, SV_PROTECT, 0, ACCESS_READ | ACCESS_WRITE | ACCESS_EXECUTE }, - }, - { - 0x800, - 0x800, - 0x800, - MMU_PAGE_SIZE_1K, - { CACHE_WRITETHROUGH, SV_PROTECT, 0, ACCESS_READ | ACCESS_WRITE | ACCESS_EXECUTE }, - }, - { - /* when the first 4k are filled with 1k pages, we can switch to 8k pages */ - 0x1000, - 0x1000, - 0xff000, - MMU_PAGE_SIZE_8K, - { CACHE_WRITETHROUGH, SV_USER, 0, ACCESS_READ | ACCESS_WRITE | ACCESS_EXECUTE }, - }, - { - /* arrived at a 1Meg border, we can switch to 1Meg pages */ - 0x100000, - 0x100000, - 0xc00000, - MMU_PAGE_SIZE_1M, - { CACHE_WRITETHROUGH, SV_USER, 0, ACCESS_READ | ACCESS_WRITE | ACCESS_EXECUTE }, - }, - /* Falcon video ram left out intentionally here (see above) */ - { - /* ROM */ - 0xe00000, - 0xe00000, - 0x100000, - MMU_PAGE_SIZE_1M, - { CACHE_WRITETHROUGH, SV_USER, 0, ACCESS_READ | ACCESS_EXECUTE }, - }, - { - /* FASTRAM */ - 0x1000000, - 0x1000000, - (uint32_t) _FASTRAM_END - 0x1000000, - MMU_PAGE_SIZE_1M, - { CACHE_WRITETHROUGH, SV_USER, 0, ACCESS_READ | ACCESS_WRITE | ACCESS_EXECUTE }, - }, - { - /* MBAR */ - MBAR_ADDRESS, - MBAR_ADDRESS, - 0x100000, - MMU_PAGE_SIZE_1M, - { CACHE_NOCACHE_PRECISE, SV_PROTECT, 0, ACCESS_READ | ACCESS_WRITE }, - }, - { - /* RAMBAR0 */ - RAMBAR0_ADDRESS, - RAMBAR0_ADDRESS, - (uint32_t) _RAMBAR0_SIZE, - MMU_PAGE_SIZE_1K, - { CACHE_WRITETHROUGH, SV_PROTECT, 0, ACCESS_READ | ACCESS_WRITE | ACCESS_EXECUTE }, - }, - { - /* RAMBAR1 */ - RAMBAR1_ADDRESS, - RAMBAR1_ADDRESS, - (uint32_t) _RAMBAR1_SIZE, - MMU_PAGE_SIZE_1K, - { CACHE_WRITETHROUGH, SV_PROTECT, 0, ACCESS_READ | ACCESS_WRITE | ACCESS_EXECUTE }, - }, - { - /* SYSTEM SRAM */ - SYS_SRAM_ADDRESS, - SYS_SRAM_ADDRESS, - (uint32_t) _SYS_SRAM_SIZE, - MMU_PAGE_SIZE_8K, - { CACHE_WRITETHROUGH, SV_PROTECT, 0, ACCESS_READ | ACCESS_WRITE | ACCESS_EXECUTE }, - }, - { - /* Firebee FPGA registers */ - (uint32_t) 0xf0000000, - (uint32_t) 0xf0000000, - (uint32_t) 0x08000000, - MMU_PAGE_SIZE_1M, - { CACHE_NOCACHE_PRECISE, SV_PROTECT, 0, ACCESS_READ | ACCESS_WRITE }, - }, - { - /* Falcon I/O registers */ - (uint32_t) 0xfff00000, - (uint32_t) 0xfff00000, - (uint32_t) 0x100000, - MMU_PAGE_SIZE_1M, - { CACHE_NOCACHE_PRECISE, SV_PROTECT, 0, ACCESS_READ | ACCESS_WRITE }, - }, - { - /* the same, but different virtual address */ - (uint32_t) 0x00f00000, - (uint32_t) 0xfff00000, - (uint32_t) 0x100000, - MMU_PAGE_SIZE_1M, - { CACHE_NOCACHE_PRECISE, SV_PROTECT, 0, ACCESS_READ | ACCESS_WRITE }, - }, - { - /* PCI memory */ - (uint32_t) PCI_MEMORY_OFFSET, - (uint32_t) PCI_MEMORY_OFFSET, - (uint32_t) PCI_MEMORY_SIZE, - MMU_PAGE_SIZE_1M, - { CACHE_NOCACHE_PRECISE, SV_PROTECT, 0, ACCESS_READ | ACCESS_WRITE }, - }, - { - /* PCI I/O */ - (uint32_t) PCI_IO_OFFSET, - (uint32_t) PCI_IO_OFFSET, - (uint32_t) PCI_IO_SIZE, - MMU_PAGE_SIZE_1M, - { CACHE_NOCACHE_PRECISE, SV_PROTECT, 0, ACCESS_READ | ACCESS_WRITE }, - } -}; - -static int num_mmu_maps = sizeof(memory_map) / sizeof(struct mmu_mapping); - -static struct mmu_mapping *lookup_mapping(uint32_t virt) -{ - int i; - - /* - * dumb, for now - */ - - for (i = 0; i < num_mmu_maps; i++) - { - if (virt >= memory_map[i].virt && virt <= memory_map[i].virt + memory_map[i].length - 1) - return &memory_map[i]; - } - return NULL; -} - void mmu_init(void) { extern uint8_t _MMUBAR[]; uint32_t MMUBAR = (uint32_t) &_MMUBAR[0]; - int i; + extern uint8_t _TOS[]; + uint32_t TOS = (uint32_t) &_TOS[0]; set_asid(0); /* do not use address extension (ASID provides virtual 48 bit addresses */ /* set data access attributes in ACR0 and ACR1 */ - - set_acr0(ACR_WRITE_PROTECT(0) | /* read and write accesses permitted */ - ACR_SUPERVISOR_PROTECT(0) | /* supervisor and user mode access permitted */ - ACR_CACHE_MODE(CACHE_NOCACHE_PRECISE) | /* cache inhibit, precise */ - ACR_ADDRESS_MASK_MODE(0) | /* region > 16 MByte */ - ACR_S(ACR_S_ALL) | /* memory visible in user and supervisor mode */ - ACR_E(1) | /* enable ACR */ + set_acr0(ACR_W(0) | /* read and write accesses permitted */ + ACR_SP(0) | /* supervisor and user mode access permitted */ + ACR_CM(ACR_CM_CACHE_INH_PRECISE) | /* cache inhibit, precise */ + ACR_AMM(0) | /* control region > 16 MB */ + ACR_S(ACR_S_ALL) | /* match addresses in user and supervisor mode */ + ACR_E(1) | /* enable ACR */ #if defined(MACHINE_FIREBEE) - ACR_ADMSK(0x3f) | /* cover 1 GB area from 0xc0000000 to 0xffffffff */ - ACR_BA(0xc0000000)); /* equals area from 3 to 4 GB */ + ACR_ADMSK(0x3f) | /* cover 1GB area from 0xc0000000 to 0xffffffff */ + ACR_BA(0xc0000000)); /* (equals area from 3 to 4 GB */ #elif defined(MACHINE_M5484LITE) - ACR_ADMSK(0x7f) | /* cover 2 GB area from 0x80000000 to 0xffffffff */ + ACR_ADMSK(0x7f) | /* cover 2 GB area from 0x80000000 to 0xffffffff */ ACR_BA(0x80000000)); #elif defined(MACHINE_M54455) - ACR_ADMSK(0x7f) | /* cover 2 GB area from 0x80000000 to 0xffffffff */ - ACR_BA(0x80000000)); + ACR_ADMSK(0x7f) | + ACR_BA(0x80000000)); /* FIXME: not determined yet */ #else -#error unknown machine +#error unknown machine! #endif /* MACHINE_FIREBEE */ - set_acr1(ACR_WRITE_PROTECT(0) | /* read and write accesses permitted */ - ACR_SUPERVISOR_PROTECT(0) | /* supervisor and user mode access permitted */ + // set_acr1(0x601fc000); + set_acr1(ACR_W(0) | + ACR_SP(0) | + ACR_CM(0) | #if defined(MACHINE_FIREBEE) - ACR_CACHE_MODE(CACHE_WRITETHROUGH) | /* video RAM on the Firebee */ + ACR_CM(ACR_CM_CACHEABLE_WT) | /* video RAM on the Firebee */ #elif defined(MACHINE_M5484LITE) - ACR_CACHE_MODE(CACHE_NOCACHE_PRECISE) | /* Compact Flash on the M548xLITE */ + ACR_CM(ACR_CM_CACHE_INH_PRECISE) | /* Compact Flash on the M548xLITE */ #elif defined(MACHINE_M54455) - ACR_CACHE_MODE(CACHE_NOCACHE_PRECISE) | /* FIXME: not clear yet */ + ACR_CM(ACR_CM_CACHE_INH_PRECISE) | /* FIXME: not determined yet */ #else -#error unknown machine -#endif - ACR_ADDRESS_MASK_MODE(0) | /* region > 16 MByte */ - ACR_S(ACR_S_ALL) | /* memory visible from user and supervisor mode */ - ACR_E(1) | /* enable ACR */ +#error unknown machine! +#endif /* MACHINE_FIREBEE */ + ACR_AMM(0) | + ACR_S(ACR_S_ALL) | + ACR_E(1) | ACR_ADMSK(0x1f) | ACR_BA(0x60000000)); + /* set instruction access attributes in ACR2 and ACR3 */ - /* - * set instruction access attributes in ACR2 and ACR3. - */ - - set_acr2(ACR_WRITE_PROTECT(0) | - ACR_SUPERVISOR_PROTECT(0) | - ACR_CACHE_MODE(CACHE_WRITETHROUGH) | - ACR_ADDRESS_MASK_MODE(1) | + //set_acr2(0xe007c400); + set_acr2(ACR_W(0) | + ACR_SP(0) | + ACR_CM(0) | + ACR_CM(ACR_CM_CACHEABLE_WT) | + ACR_AMM(1) | ACR_S(ACR_S_ALL) | ACR_E(1) | - ACR_ADMSK(0x07) | + ACR_ADMSK(0x7) | ACR_BA(0xe0000000)); - set_acr3(0); /* disable ACR3 */ - set_mmubar(MMUBAR + 1); /* set and enable MMUBAR */ + /* disable ACR3 */ + set_acr3(0x0); + + set_mmubar(MMUBAR + 1); /* set and enable MMUBAR */ /* clear all MMU TLB entries */ MCF_MMU_MMUOR = MCF_MMU_MMUOR_CA; - /* map locked TLB entries */ - 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); + /* create locked TLB entries */ - if (locked_map[i].flags.page_id == SCA_PAGE_ID) - { - video_tlb = 0x2000; - video_sbt = 0x0; - } - } + /* + * 0x0000'0000 - 0x000F'FFFF (first MB of physical memory) locked virtual = physical + */ + MCF_MMU_MMUTR = 0x0 | /* virtual address */ + MCF_MMU_MMUTR_SG | /* shared global */ + MCF_MMU_MMUTR_V; /* valid */ + MCF_MMU_MMUDR = 0x0 | /* physical address */ + MCF_MMU_MMUDR_SZ(0) | /* 1 MB page size */ + MCF_MMU_MMUDR_CM(0x1) | /* cacheable, copyback */ + MCF_MMU_MMUDR_R | /* read access enable */ + MCF_MMU_MMUDR_W | /* write access enable */ + MCF_MMU_MMUDR_X | /* execute access enable */ + MCF_MMU_MMUDR_LK; /* lock entry */ + MCF_MMU_MMUOR = MCF_MMU_MMUOR_ACC | /* access TLB, data */ + MCF_MMU_MMUOR_UAA; /* update allocation address field */ + MCF_MMU_MMUOR = MCF_MMU_MMUOR_ITLB | /* instruction */ + MCF_MMU_MMUOR_ACC | /* access TLB */ + MCF_MMU_MMUOR_UAA; /* update allocation address field */ + + /* + * 0x00d0'0000 - 0x00df'ffff (last megabyte of ST RAM = Falcon video memory) locked ID = 6 + * mapped to physical address 0x60d0'0000 (FPGA video memory) + * video RAM: read write execute normal write true + */ + + MCF_MMU_MMUTR = 0x00d00000 | /* virtual address */ +#if defined(MACHINE_FIREBEE) + MCF_MMU_MMUTR_ID(SCA_PAGE_ID) | +#endif /* MACHINE_FIREBEE */ + MCF_MMU_MMUTR_SG | /* shared global */ + MCF_MMU_MMUTR_V; /* valid */ +#if defined(MACHINE_FIREBEE) + /* map FPGA video memory for FireBee only */ + MCF_MMU_MMUDR = 0x60d00000 | /* physical address */ +#elif defined(MACHINE_M5484LITE) + MCF_MMU_MMUDR = 0x00d00000 | /* physical address */ +#elif defined(MACHINE_M54455) + MCF_MMU_MMUDR = 0x60d00000 | /* FIXME: not determined yet */ +#else +#error unknown machine! +#endif /* MACHINE_FIREBEE */ + MCF_MMU_MMUDR_SZ(0) | /* 1 MB page size */ + MCF_MMU_MMUDR_CM(0x0) | /* cachable writethrough */ + /* caveat: can't be supervisor protected since TOS puts the application stack there! */ + //MCF_MMU_MMUDR_SP | /* supervisor protect */ + MCF_MMU_MMUDR_R | /* read access enable */ + MCF_MMU_MMUDR_W | /* write access enable */ + MCF_MMU_MMUDR_X | /* execute access enable */ + MCF_MMU_MMUDR_LK; /* lock entry */ + MCF_MMU_MMUOR = MCF_MMU_MMUOR_ACC | /* access TLB, data */ + MCF_MMU_MMUOR_UAA; /* update allocation address field */ + MCF_MMU_MMUOR = MCF_MMU_MMUOR_ITLB | /* instruction */ + MCF_MMU_MMUOR_ACC | /* access TLB */ + MCF_MMU_MMUOR_UAA; /* update allocation address field */ + +#if defined(MACHINE_FIREBEE) + video_tlb = 0x2000; /* set page as video page */ + video_sbt = 0x0; /* clear time */ +#endif /* MACHINE_FIREBEE */ + + /* + * Make the TOS (in SDRAM) read-only + * This maps virtual 0x00e0'0000 - 0x00ef'ffff to the same virtual address + */ + MCF_MMU_MMUTR = TOS | /* virtual address */ + MCF_MMU_MMUTR_SG | /* shared global */ + MCF_MMU_MMUTR_V; /* valid */ + MCF_MMU_MMUDR = TOS | /* physical address */ + MCF_MMU_MMUDR_SZ(0) | /* 1 MB page size */ + MCF_MMU_MMUDR_CM(0x1) | /* cachable copyback */ + MCF_MMU_MMUDR_R | /* read access enable */ + //MCF_MMU_MMUDR_W | /* write access enable (FIXME: for now) */ + MCF_MMU_MMUDR_X | /* execute access enable */ + MCF_MMU_MMUDR_LK; /* lock entry */ + MCF_MMU_MMUOR = MCF_MMU_MMUOR_ACC | /* access TLB, data */ + MCF_MMU_MMUOR_UAA; /* update allocation address field */ + MCF_MMU_MMUOR = MCF_MMU_MMUOR_ITLB | /* instruction */ + MCF_MMU_MMUOR_ACC | /* access TLB */ + MCF_MMU_MMUOR_UAA; /* update allocation address field */ + +#if MACHINE_FIREBEE + /* + * Map FireBee I/O area (0xfff0'0000 - 0xffff'ffff physical) to the Falcon-compatible I/O + * area (0x00f0'0000 - 0x00ff'ffff virtual) for the FireBee + */ + + MCF_MMU_MMUTR = 0x00f00000 | /* virtual address */ + MCF_MMU_MMUTR_SG | /* shared global */ + MCF_MMU_MMUTR_V; /* valid */ + MCF_MMU_MMUDR = 0xfff00000 | /* physical address */ + MCF_MMU_MMUDR_SZ(0) | /* 1 MB page size */ + MCF_MMU_MMUDR_CM(0x2) | /* nocache precise */ + MCF_MMU_MMUDR_SP | /* supervisor protect */ + MCF_MMU_MMUDR_R | /* read access enable */ + MCF_MMU_MMUDR_W | /* write access enable */ + MCF_MMU_MMUDR_X | /* execute access enable */ + MCF_MMU_MMUDR_LK; /* lock entry */ + MCF_MMU_MMUOR = MCF_MMU_MMUOR_ACC | /* access TLB, data */ + MCF_MMU_MMUOR_UAA; /* update allocation address field */ + MCF_MMU_MMUOR = MCF_MMU_MMUOR_ITLB | /* instruction */ + MCF_MMU_MMUOR_ACC | /* access TLB */ + MCF_MMU_MMUOR_UAA; /* update allocation address field */ +#endif /* MACHINE_FIREBEE */ + + /* + * Map (locked) the second last MB of physical SDRAM (this is where BaS .data and .bss reside) to the same + * virtual address. This is also used when BaS is in RAM + */ + + MCF_MMU_MMUTR = (SDRAM_START + SDRAM_SIZE - 0x00200000) | /* virtual address */ + MCF_MMU_MMUTR_SG | /* shared global */ + MCF_MMU_MMUTR_V; /* valid */ + MCF_MMU_MMUDR = (SDRAM_START + SDRAM_SIZE - 0x00200000) | /* physical address */ + MCF_MMU_MMUDR_SZ(0) | /* 1 MB page size */ + MCF_MMU_MMUDR_CM(0x0) | /* cacheable writethrough */ + MCF_MMU_MMUDR_SP | /* supervisor protect */ + MCF_MMU_MMUDR_R | /* read access enable */ + MCF_MMU_MMUDR_W | /* write access enable */ + MCF_MMU_MMUDR_X | /* execute access enable */ + MCF_MMU_MMUDR_LK; /* lock entry */ + MCF_MMU_MMUOR = MCF_MMU_MMUOR_ACC | /* access TLB, data */ + MCF_MMU_MMUOR_UAA; /* update allocation address field */ + MCF_MMU_MMUOR = MCF_MMU_MMUOR_ITLB | /* instruction */ + MCF_MMU_MMUOR_ACC | /* access TLB */ + MCF_MMU_MMUOR_UAA; /* update allocation address field */ + + /* + * Map (locked) the very last MB of physical SDRAM (this is where the driver buffers reside) to the same + * virtual address. Used uncached for drivers. + */ + + MCF_MMU_MMUTR = (SDRAM_START + SDRAM_SIZE - 0x00100000) | /* virtual address */ + MCF_MMU_MMUTR_SG | /* shared global */ + MCF_MMU_MMUTR_V; /* valid */ + MCF_MMU_MMUDR = (SDRAM_START + SDRAM_SIZE - 0x00100000) | /* physical address */ + MCF_MMU_MMUDR_SZ(0) | /* 1 MB page size */ + MCF_MMU_MMUDR_CM(0x2) | /* nocache precise */ + MCF_MMU_MMUDR_SP | /* supervisor protect */ + MCF_MMU_MMUDR_R | /* read access enable */ + MCF_MMU_MMUDR_W | /* write access enable */ + //MCF_MMU_MMUDR_X | /* execute access enable */ + MCF_MMU_MMUDR_LK; /* lock entry */ + MCF_MMU_MMUOR = MCF_MMU_MMUOR_ACC | /* access TLB, data */ + MCF_MMU_MMUOR_UAA; /* update allocation address field */ + MCF_MMU_MMUOR = MCF_MMU_MMUOR_ITLB | /* instruction */ + MCF_MMU_MMUOR_ACC | /* access TLB */ + MCF_MMU_MMUOR_UAA; /* update allocation address field */ } -/* - * handle an access error - * upper level routine called from access_exception inside exceptions.S - */ -bool access_exception(uint32_t pc, uint32_t format_status) +void mmutr_miss(uint32_t address) { - int fault_status; - uint32_t fault_address; - uint32_t mmu_status; + dbg("MMU TLB MISS at 0x%08x\r\n", address); + flush_and_invalidate_caches(); - /* - * extract fault status from format_status exception stack field - */ - fault_status = format_status & 0xc030000; - mmu_status = MCF_MMU_MMUSR; - - /* - * determine if access fault was caused by a TLB miss - */ - switch (fault_status) + switch (address) { - case 0x4010000: /* TLB miss on opword of instruction fetch */ - case 0x4020000: /* TLB miss on extension word of instruction fetch */ - //fault_address = pc; - //break; - case 0x8020000: /* TLB miss on data write */ - case 0xc020000: /* TLB miss on data read or read-modify-write */ - fault_address = MCF_MMU_MMUAR; - /* - * the following line must stay commented or we risk a double fault (debugging - * output requiring itself a page mapping): - */ - // dbg("access fault - TLB miss at %p. Fault status = 0x0%x\r\n", pc, fault_status); + case keyctl: + case keybd: + /* do something to emulate the IKBD access */ + dbg("IKBD access\r\n"); + break; + + case midictl: + case midi: + /* do something to emulate MIDI access */ + dbg("MIDI ACIA access\r\n"); break; default: - return false; + /* add missed page to TLB */ + MCF_MMU_MMUTR = (address & 0xfff00000) | /* virtual aligned to 1M */ + MCF_MMU_MMUTR_SG | /* shared global */ + MCF_MMU_MMUTR_V; /* valid */ + + MCF_MMU_MMUDR = (address & 0xfff00000) | /* physical aligned to 1M */ + MCF_MMU_MMUDR_SZ(0) | /* 1 MB page size */ + MCF_MMU_MMUDR_CM(0x1) | /* cacheable copyback */ + MCF_MMU_MMUDR_R | /* read access enable */ + MCF_MMU_MMUDR_W | /* write access enable */ + MCF_MMU_MMUDR_X; /* execute access enable */ + + MCF_MMU_MMUOR = MCF_MMU_MMUOR_ACC | /* access TLB, data */ + MCF_MMU_MMUOR_UAA; /* update allocation address field */ + + MCF_MMU_MMUOR = MCF_MMU_MMUOR_ITLB | /* instruction */ + MCF_MMU_MMUOR_ACC | /* access TLB */ + MCF_MMU_MMUOR_UAA; /* update allocation address field */ } - - - 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 - */ - return false; - } - else - { - struct mmu_mapping *map; - - - if ((map = lookup_mapping(fault_address)) != NULL) - { - uint32_t mask; - - switch (map->pagesize) - { - case MMU_PAGE_SIZE_1M: - mask = ~(0x100000 - 1); - break; - case MMU_PAGE_SIZE_4K: - mask = ~(0x1000 - 1); - break; - case MMU_PAGE_SIZE_8K: - mask = ~(0x2000 - 1); - break; - case MMU_PAGE_SIZE_1K: - mask = ~(0x400 - 1); - break; - } - - mmu_map_page(fault_address & mask, fault_address & mask, map->pagesize, map->flags); - return true; - } - } - return false; -} - - -void mmu_map_page(uint32_t virt, uint32_t phys, uint32_t map_size, struct map_flags flags) -{ - - /* - * add page to TLB - */ - MCF_MMU_MMUTR = virt | /* virtual address */ - MCF_MMU_MMUTR_ID(flags.page_id) | - MCF_MMU_MMUTR_SG | /* shared global */ - MCF_MMU_MMUTR_V; /* valid */ - - MCF_MMU_MMUDR = phys | /* physical address */ - MCF_MMU_MMUDR_SZ(map_size) | /* 1 MB page size */ - MCF_MMU_MMUDR_CM(flags.cache_mode) | - (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_EXECUTE ? MCF_MMU_MMUDR_X : 0); /* execute access enable */ - - MCF_MMU_MMUOR = MCF_MMU_MMUOR_ACC | /* access TLB, data */ - MCF_MMU_MMUOR_UAA; /* update allocation address field */ - - MCF_MMU_MMUOR = MCF_MMU_MMUOR_ITLB | /* instruction */ - MCF_MMU_MMUOR_ACC | /* access TLB */ - MCF_MMU_MMUOR_UAA; /* update allocation address field */ - dbg("mapped virt=%p to phys=%p\r\n", virt, phys); }