;*************************************************************************
;** mmu.library                                                         **
;**                                                                     **
;** a system library for arbitration and control of the MC68K MMUs      **
;**                                                                     **
;** © 1998 THOR-Software, Thomas Richter                                **
;** No commercial use, reassembly, modification without prior, written  **
;** permission of the authors.                                          **
;** Including this library in any commercial software REQUIRES a        **
;** written permission and the payment of a small fee.                  **
;**                                                                     **
;** This is an internal header file, do not depend on anything here.    **
;** Use the official include files.                                     **
;** Distributed only for the mmu.library development group for private  **
;** use.                                                                **
;**                                                                     **
;**---------------------------------------------------------------------**
;** Block: 68030 specific routines                                      **
;** Version 0.02                19.09.1998      © THOR                  **
;*************************************************************************

;FOLD Includes
        include mu_lib.i
        include mu_context.i
        include mu_alerts.i
;ENDFOLD
;FOLD External references
        xref SubSuper
        xref MUAlert
        xref AddTransparentTranslation
        xref Parse030
;ENDFOLD

        section main_code,code

        machine mc68030
        pmmu

;FOLD Init030
;*************************************************
;** Init030                                     **
;** Initialize internal vectors of the library  **
;** base for the use of the 68030 MMU           **
;**                                             **
;** *a6 = library base                          **
;** returns success/failure in d0               **
;*************************************************
        xdef Init030
Init030:
        lea ReadConfig(pc),a0
        move.l a0,2+mulib_ReadConfig(a6)        ;no need to flush the cache, that's done by the library anyways
        lea WriteConfig(pc),a0
        move.l a0,2+mulib_WriteConfig(a6)
        lea SetLibrary(pc),a0
        move.l a0,2+mulib_SetLibrary(a6)
        lea Parse030(pc),a0
        move.l a0,2+mulib_ParseMMU(a6)
        lea ParseTT(pc),a0
        move.l a0,2+mulib_ParseTT(a6)
        moveq #1,d0
        rts
;ENDFOLD
;FOLD ReadConfig
;*************************************************
;** ReadConfig                                  **
;** Read the MMU configuration                  **
;** to *a0 struct MMUConfig                     **
;*************************************************
ReadConfig:
        pea _ReadConfig(pc)
        bsr SubSuper
        rts
_ReadConfig:
        pmove tc,mcf_translationctrl(a0)        ;read the translation control register
        tst.l mcf_translationctrl(a0)           ;get it
        bpl.s .disabled                         ;if disabled, ignore it
        pmove crp,mcf_userrootpointer(a0)
        and.w #3,2+mcf_userrootpointer(a0)      ;avoid trouble and clear unused bits
        pmove tt0,mcf_dtt0(a0)                  ;transparent translation 0
        pmove tt1,mcf_dtt1(a0)                  ;transparent translation 1
        btst #1,mcf_translationctrl(a0)         ;SRP used?
        beq.s .disabled
        pmove srp,mcf_superrootpointer(a0)
        and.w #3,2+mcf_superrootpointer(a0)     ;avoid trouble and clear unused bits
.disabled:
        rte
;ENDFOLD
;FOLD WriteConfig
;*************************************************
;** WriteConfig                                 **
;** install the MMU configuration in *a0        **
;*************************************************
WriteConfig:
        pea _WriteConfig(pc)
        bsr SubSuper
        rts
_WriteConfig:
        ori.w #$0700,sr                         ;all interrupts off
                                                ;here: enable it
        clr.l -(a7)
        movec.l cacr,d0
        pmove (a7),tc                           ;clear translation control
        pmove (a7),tt0
        pmove (a7),tt1
        or.w #$808,d0                           ;prepare for flush
        tst.l mcf_translationctrl(a0)           ;MMU disabled ?
        bpl.s .disableme
        pmove mcf_userrootpointer(a0),crp
        btst #1,mcf_translationctrl(a0)
        beq.s .nosrp
        pmove mcf_superrootpointer(a0),srp      ;write urp,srp
.nosrp:
        pmove mcf_translationctrl(a0),tc        ;translation control
.disableme:
        tst.w 2+mcf_dtt0(a0)                    ;enabled ?
        bpl.s .isdisabled0
        pmove mcf_dtt0(a0),tt0
.isdisabled0:
        tst.w 2+mcf_dtt1(a0)
        bpl.s .isdisabled1
        pmove mcf_dtt1(a0),tt1
.isdisabled1:
        movec.l d0,cacr                         ;flush the cache
        pflusha                                 ;flush address translation cache
        addq.l #4,a7
        rte
;ENDFOLD
;FOLD SetLibrary
;*************************************************
;** SetLibrary                                  **
;** set the data in the library base from       **
;** the MMUConfig *a0                           **
;*************************************************
SetLibrary:
        move.l mcf_translationctrl(a0),d0       ;get TC
        bpl.s .disabled                         ;is it enabled ?
                                                ;here yes: Read the values and life with them
        bfextu d0{12:4},d1
        move.b d1,mulib_InitialShift(a6)
        bfextu d0{16:4},d1
        move.b d1,mulib_LevelABits(a6)
        bfextu d0{20:4},d1
        move.b d1,mulib_LevelBBits(a6)
        bfextu d0{24:4},d1
        move.b d1,mulib_LevelCBits(a6)
        bfextu d0{28:4},d1
        move.b d1,mulib_LevelDBits(a6)
        bfextu d0{8:4},d1
        move.b d1,mulib_PageBits(a6)
                                                ;now fill in the root pointers in the library base
        bra.s .setmasks
.disabled:
                                                ;default: Mimic the '060 page layout
        move.b #12,mulib_PageBits(a6)           ;Page size is 4K
        move.b #6,mulib_LevelCBits(a6)          ;6 Bits for Level C
        move.b #7,mulib_LevelBBits(a6)          ;7 Bits for Level D
        move.b #7,mulib_LevelABits(a6)          ;7 Bits for Level A
        clr.b mulib_InitialShift(a6)
        clr.b mulib_LevelDBits(a6)              ;no Level D, no Initial Shift
.setmasks:
        move.l #$0010,d0
        move.l d0,mulib_LevelAAlign(a6)
        move.l d0,mulib_LevelBAlign(a6)
        move.l d0,mulib_LevelCAlign(a6)
        move.l d0,mulib_LevelDAlign(a6)
        subq.l #1,d0
        not.l d0
        move.l d0,mulib_LevelAMask(a6)
        move.l d0,mulib_LevelBMask(a6)
        move.l d0,mulib_LevelCMask(a6)
        move.l d0,mulib_LevelDMask(a6)
        move.l #~3,mulib_IndirectMask(a6)

        moveq #0,d0
        move.b mulib_PageBits(a6),d1            ;get the page size
        bset d1,d0
        move.l d0,mulib_PageAlign(a6)           ;this is the page size, too
        subq.l #1,d0
        not.l d0
        move.l d0,mulib_PageMask(a6)            ;all valid bits in the address
        moveq #0,d0
        move.b mulib_InitialShift(a6),d0        ;do we have an initial shift ?
        beq.s .noinitialshift
        moveq #32,d1
        sub.b d0,d1
        moveq #0,d0
        bset d1,d0                              ;this is the highest possible address
                                                ;all other address lines are ignored
.noinitialshift:
        move.l d0,mulib_UpperEnd(a6)
        rts
;ENDFOLD
;FOLD ParseTT
;*************************************************
;** ParseTT                                     **
;** Add the modifications made thru the         **
;** transparent translation registers           **
;** *a1=MMUConfig                               **
;** *a0=Context                                 **
;*************************************************
ParseTT:
        move.l mcf_dtt0(a1),d0
        bsr _ParseTT
        beq.s .exit
        move.l mcf_dtt1(a1),d0
        bsr _ParseTT
.exit:
        rts
_ParseTT:
        movem.l a0-a1,-(a7)

        tst.w d0
        bpl.s .disabled                         ;TC is disabled, ingore

        move.l #(1<<mapp_translated),d1         ;do not touch this region
        swap d0
        move.l d0,a1

        move.l d1,d0
        bsr AddTransparentTranslation
        bra.s .exit
.disabled:
        moveq #1,d0
.exit:
        movem.l (a7)+,a0-a1
        rts
;ENDFOLD

