* Diese Programm legt im Speicher zwei 4 KByte
* große Seiten an. Diese Seiten werden den
* logischen Adressen $C0000000 und $C0001000 zuge-
* wiesen. Die zweite Seite ist zusätzlich noch
* schreibgeschüzt. Wird die logische Adresse
* $C0002000 angesprochen, wird ein Bus-Fehler aus-
* gelöst. Wenn sie das Programm starten und es
* passiert nichts, wissen sie, daß alles geklappt
* hat. Blinkt der Bildschirm ist irgend etwas
* nicht in Ordnung.

  MC68030

  include 'exec/exec_lib.i'
  include 'exec/memory.i'
  include 'intuition/intuition_lib.i'

  move.l #PageMemLen+4096,d0  ; Diese Zeilen sind
  move.l #MEMF_CLEAR,d1
  CALLEXEC AllocVec
  tst.l d0
  bne MemOk
  bsr Flash
  bra NoMem
MemOk:
  move.l d0,-(sp)
  add.l #4096,d0
  lsr.l #8,d0  ; nur dafür gedacht
  lsr.l #4,d0
  lsl.l #8,d0
  lsl.l #4,d0
  move.l d0,a5
  lea.l LevelA-Page0(a5),a0
  move.l a0,RootPointerDesc+4
  lea.l LevelB-Page0(a5),a0
  move.l a0,LevelA+100  ; die Seiten auf eine
  lea.l LevelC-Page0(a5),a0
  move.l a0,LevelB+4
  lea.l $01(a5),a0
  move.l a0,LevelC
  lea.l Page1-Page0+$05(a5),a0  ; gerade 4 KByte-
  move.l a0,LevelC+4 ; Grenze
  lea.l Page0,a0
  move.l a5,a1
  move.l #PageMemLen,d0
  CALLEXEC CopyMem  ; zu bringen.

  CALLEXEC SuperState
  movec vbr,a0
  move.l 8(a0),a4  ; Vektor für Bus-Fehler retten
  move.l #HandleExcept,8(a0)
  ; eigen Routine eintragen
  pmove tc,OldTCValue   ; normalerweise sollte man
  ; prüfen, ob das Enable-Bit gesetzt ist. Und wenn
  ; dies der Fall ist, sollte man die MMU nicht be-
  ; nutzen. Aber es sollten auf jeden Fall alle Re-
  ; gister am Ende wieder hergestellt werden.
  pmove ClearTC,tc
  pmove crp,OldRootPointerDesc
  pflusha
  pmove RootPointerDesc,crp
  pmove TCValue,tc
  CALLEXEC UserState

  move.l #'Test',$C0000000  ; $C0000000 = Page0
  move.l $C0000000,d0
  cmp.l (a5),d0  ; Adresse von Page0 in a5
  beq Page0Ok
  bsr Flash
Page0Ok:
  move.w #'WP',$C0001000  ; $C0001000 = Page1
  cmp.w #$3210,$C0001000
  ; unverändert, da Screibschutz
  beq Page1Ok
  bsr Flash
Page1Ok:
  move.l $C0002000,d0  ; hier tritt Bus-Fehler auf
  bsr Flash

Ende:
  CALLEXEC SuperState
  movec vbr,a0
  move.l a4,8(a0)  ; alten Vektor wieder herstellen
  pmove ClearTC,tc
  pflusha
*  pmove OldRootPointerDesc,crp  ; Die alten Werte
*  pmove OldTCValue,tc         ; dürfen nur wieder
  ; hergestellt werden, wenn man vorher geprüft ob
  ; diese Werte auch gültig sind und keine Exception
  ; auslösen.
  CALLEXEC UserState
  move.l (sp)+,a1
  CALLEXEC FreeVec
NoMem:
  rts

HandleExcept:
  move.l $10(sp),a0      ; Fehleradresse
  cmp.l #$C0001000,a0    ; die schreibgeschützte
  beq WriteProtect       ; Seite ?
  cmp.l #$C0002000,a0    ; die ungültige
  beq Invalid            ; Seite ?
OtherErr:
  jmp (a4)               ; alter Exceptionhandler
Invalid:
  move.w 6(sp),d0
  lsr.w #8,d0
  lsr.w #4,d0
  moveq #24,d1
  cmp.w #$B,d0
  bne ShortStack
  add.w #60,d1
ShortStack:
  move.l (sp),0(sp,d1)
  move.l 4(sp),4(sp,d1)
  lea.l 0(sp,d1),sp
  move.l #Ende,2(sp)  ; Rücksprungadresse ändern
  and.w #$0FFF,6(sp)
  rte
WriteProtect:
  bclr.b #0,$A(sp)
  rte

Flash:
  lea.l IntName,a1
  moveq #0,d0
  CALLEXEC OpenLibrary
  tst.l d0
  beq ExitFlash
  move.l d0,a6
  sub.l a0,a0
  jsr _LVODisplayBeep(a6)
  move.l a6,a1
  CALLEXEC CloseLibrary
ExitFlash:
  rts

TCValue:
  dc.l %10000000110000000100100010000000
OldTCValue:
  dc.l 0
ClearTC:
  dc.l 0
MMUSRReg:
  dc.w 0
* E=1 / SRE+FCL=0 / PS=1100=4KByte / IS=0 / TIA=4 /
* TIB=8 / TIC=8 /TID=0
RootPointerDesc:
  dc.l $80000003,LevelA
OldRootPointerDesc:
  dc.l $00000000,$00000000
* L/U=1 / LIMIT=0 / DT=3=8 Byte-Tabelle / Adresse
* der Tabelle

Page0:
  dc.w $0123
  ds.b 4094  ; Jede Seite hat 4 KByte
Page1:
  dc.w $3210
  ds.b 4094

LevelA:
  dc.l $8000FC01,$00000000 ; Early-Termination
  dc.l $8000FC01,$10000000 ; es wird so übersetzt,
  dc.l $8000FC01,$20000000 ; daß die physikalische
  dc.l $8000FC01,$30000000 ; gleich der logischen
  dc.l $8000FC01,$40000000 ; ist. Diese Tabelle ist
  dc.l $8000FC01,$50000000 ; nicht eingeschränkt.
  dc.l $8000FC01,$60000000
  dc.l $8000FC01,$70000000
  dc.l $8000FC01,$80000000
  dc.l $8000FC01,$90000000
  dc.l $8000FC01,$A0000000
  dc.l $8000FC01,$B0000000
  dc.l $0000FC03,LevelB ; Außer hier, wo unsere
  ; nächste Tabelle folgt, die auf den Eintrag 0
  ; begrenzt ist.
  dc.l $8000FC01,$D0000000
  dc.l $8000FC01,$E0000000
  dc.l $8000FC01,$F0000000

LevelB:
  dc.l $0002FC02,LevelC ; Zeiger auf 4 Byte-Tabelle,
  ; die auf zwei Einträge (0 und 1) limitiert ist.

  dc.l 0,0  ; Pad auf 16 Byte-Grenze
LevelC:
  dc.l Page0+$01  ; Zeiger auf Seite
  dc.l Page1+$05  ; Zeiger auf Seite und
  ; Screibschutz
  dc.l $00000000  ; ungültiger Descriptor
PageMemLen EQU *-Page0

IntName:
  dc.b 'intuition.library',0

		END
