;*************************************************************************
;** 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: Detect.a                                                     **
;** Detect a possible MMU, return the type in d0                        **
;** Version 0.01                15.09.1998              © THOR          **
;*************************************************************************

;FOLD Includes
        include INC:exec_lib.asm
        include mu_lib.i
;ENDFOLD
;FOLD Externals
        xref SubSuper
;ENDFOLD

        section main_code,code

;FOLD DetectMMUType
;*************************************************
;** DetectMMUType                               **
;** Return the type of the MMU installed        **
;** this does NOT YET check whether an EC type  **
;** processor is installed, this must be done   **
;** manually afterwards. It checks only the     **
;** possible type of the MMU                    **
;*************************************************
        xdef DetectMMUType
DetectMMUType:
        move.b mulib_AttnFlags(a6),d1           ;get CPU type

        btst #AF_68060,d1
        bne.s .found060
        tst.l mulib_060Base(a6)
        bne.s .found060

        btst #AF_68040,d1
        bne.s .found040

        moveq #mutype_none,d0
        btst #AF_68020,d1                       ;not even a '020?
        beq.s .found                            ;if so, exit

                                                ;check here whether MMU is available
        pea Check020MMU(pc)
        bsr SubSuper                            ;run this
        tst.l d0                                ;what is it?
        beq.s .found                            ;nothing ?

        moveq #mutype_68030,d0
        btst #AF_68030,mulib_AttnFlags(a6)      ;is the '030 installed ?
        bne.s .found

        moveq #mutype_68851,d0
        bra.s .found
.found060:
        bset #AF_68060,mulib_AttnFlags(a6)
        pea Check060MMU(pc)
        bsr SubSuper
        tst.l d0
        beq.s .found

        moveq #mutype_68060,d0
        bra.s .found
.found040:
        bset #AF_68040,mulib_AttnFlags(a6)
        pea Check040MMU(pc)
        bsr SubSuper
        tst.l d0
        beq.s .found

        moveq #mutype_68040,d0
.found:
        rts
;ENDFOLD
;FOLD Check020MMU
;*************************************************
;** Check020MMU                                 **
;** Check, whether a 68851 is on board          **
;*************************************************

        machine mc68020
        pmmu

Check020MMU:
        ori.w #$0700,sr                 ;disable interrupts
        lea -$e4(a7),a7                 ;reserve room for termporary
                                        ;exception vectors
        movec.l vbr,a0                  ;saveback VBR
        lea .illegal(pc),a1             ;entry for Illegal/LineF
        move.l a1,$10(a7)               ;set it
        move.l a1,$2c(a7)               ;ditto
        lea .nmi(pc),a1
        move.l a1,$7c(a7)               ;NMI disable
        lea .config(pc),a1
        move.l a1,$e0(a7)
        movec.l a7,vbr                  ;VBR temporary on stack
        clr.l 4(a7)                     ;clear this
        moveq #1,d0                     ;default result is: YES
        pmove tc,(a7)                   ;try to read translation control
        pmove 4(a7),tc                  ;try to write it
        tst.l (a7)                      ;Enabled ?
        bpl.s .continue                 ;continue if disabled
        pmove (a7),tc                   ;is enabled. If so, must be valid
.continue:
        movec.l a0,vbr                  ;restore VBR
                                        ;result is in d0
        lea $e4(a7),a7                  ;release stack
.nmi:
        rte                             ;this restores interrupts anyways
.illegal:
        moveq #0,d0
        addq.l #8,a7                    ;remove exception stack frame
        bra.s .continue
.config:
        moveq #0,d0
        addq.l #8,a7
        addq.l #4,a7
        bra.s .continue                 ;MMU configuration error
;ENDFOLD
;FOLD Check040MMU
;*************************************************
;** Check040MMU                                 **
;** Check, whether a 68040 MMU is on board      **
;*************************************************

        machine mc68040

Check040MMU:
        ori.w #$0700,sr                 ;disable interrupts
        lea -$80(a7),a7                 ;reserve room for termporary
                                        ;exception vectors
        movec.l vbr,a0                  ;saveback VBR
        lea .illegal(pc),a1             ;entry for Illegal/LineF
        move.l a1,$10(a7)               ;set it
        move.l a1,$2c(a7)               ;ditto
        lea .nmi(pc),a1
        move.l a1,$7c(a7)               ;NMI disable
        movec.l a7,vbr                  ;VBR temporary on stack
        moveq #1,d0                     ;default result is: YES
        moveq #0,d1
        sub.l a1,a1
        movec.l tc,d1                   ;try to read translation control
        movec.l a1,tc                   ;try to clear it
        tst.w d1                        ;enabled ?
        bpl.s .continue
        movec.l d1,tc                   ;if enabled, write back
.continue:
        movec.l a0,vbr                  ;restore VBR
                                        ;result is in d0
        lea $80(a7),a7                  ;release stack
.nmi:
        rte                             ;this restores interrupts anyways
.illegal:
        moveq #0,d0
        addq.l #8,a7                    ;remove exception stack frame
        bra.s .continue
;ENDFOLD
;FOLD Check060MMU
;*************************************************
;** Check060MMU                                 **
;** Check, whether a 68060 MMU is on board      **
;*************************************************

        machine mc68060

Check060MMU:
        ori.w #$0700,sr                 ;disable interrupts
        lea -$80(a7),a7                 ;reserve room for termporary
                                        ;exception vectors
        movec.l vbr,a0                  ;saveback VBR
        lea .illegal(pc),a1             ;entry for Illegal/LineF
        move.l a1,$10(a7)               ;set it
        move.l a1,$2c(a7)               ;ditto
        lea .nmi(pc),a1
        move.l a1,$7c(a7)               ;NMI disable
        movec.l a7,vbr                  ;VBR temporary on stack
        moveq #0,d0
        movec.l pcr,d1
        swap d1
        cmp.w #%0000010000110000,d1
        bne.s .continue
        moveq #1,d0                     ;default result is: YES
        moveq #0,d1
        sub.l a1,a1
        movec.l tc,d1                   ;try to read translation control
        movec.l a1,tc                   ;try to clear it
        tst.w d1                        ;enabled ?
        bpl.s .continue
        movec.l d1,tc                   ;if enabled, write back
.continue:
        movec.l a0,vbr                  ;restore VBR
                                        ;result is in d0
        lea $80(a7),a7                  ;release stack
.nmi:
        rte                             ;this restores interrupts anyways
.illegal:
        moveq #0,d0
        addq.l #8,a7                    ;remove exception stack frame
        bra.s .continue
;ENDFOLD
;FOLD ReadVBR
;*************************************************
;** ReadVBR                                     **
;** read the vector base register -> a0         **
;** this is not necessarely fast, but executes  **
;** fine in user mode                           **
;*************************************************
        machine mc68010

        xdef ReadVBR
ReadVBR:
        sub.l a0,a0
        btst #AF_68010,mulib_AttnFlags(a6)      ;only 68010 and up
        beq.s .exit
        pea _ReadVBR(pc)
        bsr SubSuper
.exit:
        rts
_ReadVBR:
        movec.l vbr,a0
        rte
;ENDFOLD

