;**********************************************************
;***'                                                  '***
;***'..........BOOT-Programm fuer BOOTRAM68k...........'***
;***'                                                  '***
;***'                                                  '***
;***'           (P)+(C) 2007  Gerald Ebert             '***
;***'                                                  '***
;**********************************************************
;***'  Version 2.06  vom  12.10.2007                   '***
;**********************************************************

;==========================================================
;
; Bootfehler Kennung mittels Blinken der Bankboot-LED:
;
; Dauerleuchten = Boot-EPROM nicht vorhanden oder fehlerhaft oder
;                 Bootprogramm kann nicht in RAM kopiert werden
; 1x Blinken    = Kein Grundprogramm gefunden
; 2x Blinken    = Zu wenig RAM. GP-EPROM kann nicht kopiert werden
;
;==========================================================

*>>>>>>>    LABELS   <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

* Fuer die jeweilige CPU diese Labels aus-/kommentieren.
* Zusaetzlich entsprechende Befehle in den Funktionen
* 'toggled', 'showgpep' und 'hidegpep'  aus-/kommentieren.
*=======   M68008   ======
*cpu         equ   1                    * M68008
*hideall     equ   $80                  * BOOT-EPROM und GP-EPROM ausblenden
*showbogp    equ   $c0                  * Grundprogramm-EPROM einblenden
*=======   M68000   ======
cpu         equ   2                    * M68000
hideall     equ   $8080                * BOOT-EPROM und GP-EPROM ausblenden
showbogp    equ   $c0c0                * Grundprogramm-EPROM einblenden
*=========================

gpkenn      equ   $5aa58001            * Grundprogramm Kennung
code_bra    equ   $6000                * OP-Code fuer bra <d16>
minram      equ   $00040000            * min. RAMgroesse mit GP-EPROM = 256 kB

keys        equ   $ffffff69*cpu        * KEY-Schalter + Ruecksetzen
bankboot    equ   $ffffffc8*cpu        * IO-Adr Bankboot-Register

bootstack   equ   $0000fffc*cpu        * Stackadresse nach RESET
bootdest    equ   $00008000*cpu        * Startadresse des Bootprogramms
banksize    equ   $00010000*cpu        * Groesse einer Speicherbank
gpepradr    equ   $00080000*cpu        * Startadresse des GP-EPROMSs
adrspend    equ   $000f0000*cpu        * Ende des Adressbereichs

*>>>>>>     VEKTOR-TABELLE   <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

   offset   $30000
   org      0

   dc.l     bootstack
   dc.l     bootstart
   df.l     64-2, bootstart
   df.l     256-64, 0

*>>>>>>     Bootprogramm ins RAM kopieren   <<<<<<<<<<<<<<<

bootstart:
   lea      bootdest,a2           * Startadresse des Ziels
bootst1:
   lea      PROGSTART(pc),a0      * Startadresse des zu kopieren Blocks
   move.w   #(PROGEND-PROGSTART+1)/2,d0 * Laenge des Blocks in words
   movea.l  a2,a1                 * Startadresse des Ziels merken
bootst2:
   move.w   (a0)+,(a1)+           * Wordweise kopieren
   dbra     d0,bootst2            * Naechstes Word

   lea      PROGSTART(pc),a0      * Startadresse des zu kopieren Blocks
   move.w   #(PROGEND-PROGSTART+1)/2,d0 * Laenge des Blocks in words
   movea.l  a2,a1                 * Startadresse des Ziels
bootst3:
   cmpm.w   (a0)+,(a1)+           * Quell- und Zieldaten gleich ?
   bne.s    bootst4               * Nein. -> neues RAM-Fenster suchen
   dbra     d0,bootst3            * Naechstes Word

   jmp      (a2)                  * Bootprogramm starten

bootst4:
   adda.l   #banksize,a2          * Naechste Speicherbank versuchen
   cmpa.l   #adrspend,a2          * Adressbereichsende erreicht?
   bge.s    bootst5               * Kein RAM gefunden, Pech gehabt. -> Abbruch
   adda.l   #banksize,a7          * Stackpointer ebenfalls verschieben
   bra.s    bootst1
bootst5:
   bra.s    bootst5               * Fehler -> Programm bleibt hier haengen

*>>>>>>     BOOT - PROGRAMM   <<<<<<<<<<<<<<<<<<<<<<<<<<<<<

PROGSTART:                        * Beginn des Bootprogramms
   bsr      hidegpep              * BOOT-EPROM ausblenden
   bsr      chkgpsp               * Ist schon ein Grundprogramm vorhanden ?
   bcc.s    gpstart               * Ja, dann starte es
   bsr      chkgpepr              * Gibt's ein GP-EPROM ?
   bcs.s    booterr1              * Kein GP gefunden, Pech gehabt. -> Abbruch
   bsr      chkram                * Hole Endadresse des ersten RAM-Bereichs
   cmpa.l   #minram,a0            * Ist genug RAM vorhanden ?
   blt.s    booterr2              * zu wenig RAM, Pech gehabt. -> Abbruch
   suba.l   #$00020000,a0         * ergibt RAM-Ende - 128 kB
   bsr      copygp                * GP-EPROM ins RAM kopieren
   adda.l   #$400,a0              * Adresszeiger hinter Vektortabelle stellen

gpstart:
   tst.b    keys.w                * INIT der KEY-Baugruppe (WICHTIG !!)
   jmp      $24(a0)               * Starte das Grundprogramm

*>>>>>>     Einsprung für Boot-Fehler. Laesst Bankboot-LED blinken

booterr1:
   moveq    #1,d1                 * 1 mal blinken - Pause
   bra.s    errblink
booterr2:
   moveq    #2,d1                 * 2 mal blinken - Pause
   bra.s    errblink
booterr3:
   moveq    #3,d1                 * 3 mal blinken - Pause
   bra.s    errblink
booterr4:
   moveq    #4,d1                 * 4 mal blinken - Pause
   *-------------------
errblink:
   asl.w    #1,d1                 * Anzahl verdoppeln, fuer ein - aus
   subq.w   #1,d1                 * wegen dbra
   move.w   d1,d2                 * Blinksequenz merken
   clr.w    d0
errblnk1:
   bsr.s    toggled               * LED an/aus
   move.w   #12000*cpu,d7         * Schleifenzaehler laden. Ergibt ca. 3-5 Hz
errblnk2:
   cmpi.l   #0,$0                 * Schleifensequenz
   cmpi.l   #0,$0
   dbra     d7,errblnk2           * ergibt 15,25 us/count fur 68008 8MHz
   dbra     d2,errblnk1
   *-------------------
   move.w   #12000*cpu,d7         * Schleifenzaehler laden.
errblnk3:
   cmpi.l   #0,$0                 * Schleifensequenz
   cmpi.l   #0,$0
   cmpi.l   #0,$0
   cmpi.l   #0,$0
   dbra     d7,errblnk3           * ergibt 29,25 us/count fur 68008 8MHz
   *-------------------
   move.w   d1,d2                 * Blinksequenz laden
   bra.s    errblnk1              * endlos so weiter machen

*>>>>>>     LED togglen

toggled:
*=======   M68008   ======
*   move.b   d0,bankboot.w         * BOOT-EPROM ein- /ausblenden. -> LED an/aus
*   eori.b   #hideall,d0           * Toggle Bankboot-Bit
*=======   M68000   ======
   move.w   d0,bankboot.w         * BOOT-EPROM ein- /ausblenden. -> LED an/aus
   eori.w   #hideall,d0           * Toggle Bankboot-Bit
   rts


*>>>>>>     GLOBALE ROUTINEN   <<<<<<<<<<<<<<<<<<<<<<<<<<<<

carryset:
   ori      #$01,ccr
   rts
carryclr:
   andi     #$fe,ccr
cende:
   rts

*>>>>>>     Ermittle ob sich an Speicheradresse a0 RAM befindet <<<<
*>>>>>>     Hilfsprozedur, Register werden nicht gesichert
;'          a0 <= zu pruefende Speicheradresse

chk1ram:
   movem.l  (a0)+,d0-d3           * Speicherzellen sichern
   movem.l  d4-d7,-(a0)           * Testpattern in Speicher schreiben
   cmp.l    (a0)+,d4              * Prüfe 1. Pattern
   bne.s    chk1ram1              * kein RAM, -> Ende
   cmp.l    (a0)+,d5              * Prüfe 2. Pattern
   bne.s    chk1ram2              * kein RAM, -> Ende
   cmp.l    (a0)+,d6              * Prüfe 3. Pattern
   bne.s    chk1ram3              * kein RAM, -> Ende
   cmp.l    (a0)+,d7              * Prüfe 4. Pattern
   bne.s    chk1ram4              * kein RAM, -> Ende
   movem.l  d0-d3,-(a0)           * Schreibe Speicherzelleninhalt zurueck
   bra      carryclr              * RAM gefunden, -> C = 0
chk1ram1:
   addq.l   #4,a0                 * Adresse korregieren
chk1ram2:
   addq.l   #4,a0                 * Adresse korregieren
chk1ram3:
   addq.l   #4,a0                 * Adresse korregieren
chk1ram4:
   movem.l  d0-d3,-(a0)           * Schreibe Speicherzelleninhalt zurueck
   bra      carryset              * Kein RAM, -> C = 1

*>>>>>>     Ermittle ob sich an Speicheradresse a0 RAM befindet <<<<
;'          a0 <= zu pruefende Speicheradresse

chkram0:
   movem.l  d0-d7/a1,-(a7)        * Erstmal Register auf Stack retten
   lea      testpatt(pc),a1       * Adresse der Testpattern holen
   movem.l  (a1)+,d4-d7           * Testpattern in Register laden
   bsr      chk1ram               * Pruefe, ob an Adresse in a0 RAM ist
   movem.l  (a7)+,d0-d7/a1        * Hole Register wieder vom Stack
   rts                            * C enthaelt Ergebnis der Pruefung

*>>>>>>     Ermittle des Ende des RAM-Bereichs   <<<<<<<<<<
;'          a0 <= Letzte RAM-Adresse + 1 in 1kB Schritten

chkram:
   movem.l  d0-d7/a1,-(a7)        * Erstmal Register auf Stack retten
   lea      testpatt(pc),a1       * Adresse der Testpattern holen
   movem.l  (a1)+,d4-d7           * Testpattern in Register laden
   moveq    #0,d0
   movea.l  d0,a0                 * Beginne Speichertest bei Adr 0
chkram1:
   bsr      chk1ram               * Pruefe, ob an Adresse in a0 RAM ist
   bcs.s    chkram2               * Kein RAM, Fertig.
   adda.l   #$400,a0              * Adresse um 1 kB erhoehen
   cmpa.l   #adrspend,a0          * Adressbereichsende erreicht ?
   bge.s    chkram2               * Ja, Fertig.
   bra.s    chkram1               * -> Weiter testen
chkram2:
   movem.l  (a7)+,d0-d7/a1        * Hole Register wieder vom Stack
   rts

*>>>>>>     Pruefe, ob an Adresse in a0 ein Grundprogramm ist
;'          a0 => zu testende Adresse

chkgp:
   cmpi.l   #gpkenn,(a0)          * GP-Kennung prüfen
   bne.s    chkgp1                * Keine Kennung -> Fehler
   cmpi.l   #cpu,$14(a0)          * CPU-Kennung muß uebereinstimmen
   bne.s    chkgp1                * Falsche CPU -> Carry=1
   cmpi.w   #code_bra,$20(a0)     * Hier muß ein 'bra <d16>' stehen
   bne.s    chkgp1                * Keine Kennung -> Carry=1
   cmpi.w   #code_bra,$24(a0)     * Hier muß ein 'bra <d16>' stehen
   bne.s    chkgp1                * Keine Kennung -> Carry=1
   bsr      chkram0               * Ist GP im RAM ?
   bcc.s    chkgp1                * Ja, das kann aber fehlerhaft sein
   bra      carryclr              * GP gefunden
chkgp1:
   bra      carryset              * Kein GP gefunden

*>>>>>>     Pruefe, ob im Adressbereich ein Grundprogramm ist
;'          a0 <= Adresse der Grundprogramm Kennung

chkgpsp:
   lea      $400,a0               * Beginne nach der Vektortabelle
chkgpsp1:
   bsr      chkgp                 * GP-Kennungen OK ?
   bcc      cende                 * Ja, Grundprogramm gefunden. Fertig
   adda.l   #$1000,a0             * Adresse um 4 kB erhoehen
   cmpa.l   #adrspend,a0          * Adressbereichsende erreicht?
   bge      carryset              * Ja, Fertig. Kein GP -> Carry=1
   bra.s    chkgpsp1              * Naechste Adresse pruefen

*>>>>>>     GP-EPROM einblenden

showgpep:
*=======   M68008   ======
*   move.b   #showbogp,bankboot.w  * GP-EPROM einblenden   (M68008)
*=======   M68000   ======
   move.w   #showbogp,bankboot.w  * GP-EPROM einblenden   (M68000)
   rts

*>>>>>>     GP-EPROM ausblenden

hidegpep:
*=======   M68008   ======
*   move.b   #hideall,bankboot.w   * GP-EPROM ausblenden   (M68008)
*=======   M68000   ======
   move.w   #hideall,bankboot.w   * GP-EPROM ausblenden   (M68000)
   rts

*>>>>>>     Pruefe, ob im GP-EPROM ein Grundprogramm ist

chkgpepr:
   movem.l  a0,-(a7)              * Erstmal Register auf Stack retten
   lea      gpepradr,a0           * GP-EPROM Adresse holen
   adda.l   #$400,a0              * Ergibt Adresse der Kennung
   bsr.s    showgpep              * GP-EPROM einblenden
   bsr      chkgp                 * GP-Kennungen OK ?
   bcs.s    chk1gpepr             * Nein, kein GP gefunden -> Carry=1
   bsr.s    hidegpep              * GP-EPROM ausblenden
   movem.l  (a7)+, a0             * Hole Register wieder vom Stack
   bra      carryclr              * GP gefunden
chk1gpepr:
   bsr.s    hidegpep              * GP-EPROM ausblenden
   movem.l  (a7)+, a0             * Hole Register wieder vom Stack
   bra      carryset              * Fehlerflag setzen

*>>>>>>     Kopiere Grundprogramm aus GP-EPROM nach a0   <<
;'          a0 => Zieladresse für Grundprogramm

copygp:
   movem.l  d0/d1/a0-a2,-(a7)     * Erstmal Register auf Stack retten
   lea      gpepradr,a2           * GP-EPROM Adresse holen
   movea.l  a2,a1
   adda.l   #banksize,a1          * ergibt GP-EPROM Speicherbereich
   cmpa.l   a1,a0                 * Liegt Zieladresse im GP-EPROM ?
   bge.s    copygp4               * Nein, oberhalb. -> Direkt kopieren
   movea.l  a0,a1
   adda.l   #banksize,a1          * ergibt Zielspeicherbereich
   cmpa.l   a1,a2                 * Liegt Zielbereich im GP-EPROM ?
   bge.s    copygp4               * Nein, unterhalb. -> Direkt kopieren
   moveq    #16-1,d0              * 16 Bloecke sind zu kopieren
copygp1:
   bsr      showgpep              * GP-EPROM einblenden
   moveq    #256-1,d1             * 4 kB pro Block werden kopiert
   lea      cpybuf(pc),a1         * Pufferadresse holen
copygp2:
   move.l   (a2)+,(a1)+           * 16 Bytes kopieren
   move.l   (a2)+,(a1)+
   move.l   (a2)+,(a1)+
   move.l   (a2)+,(a1)+
   dbra     d1,copygp2
   bsr      hidegpep              * GP-EPROM ausblenden
   moveq    #256-1,d1             * 4 kB pro Block werden kopiert
   lea      cpybuf(pc),a1         * Pufferadresse holen
copygp3:
   move.l   (a1)+,(a0)+           * 16 Bytes kopieren
   move.l   (a1)+,(a0)+
   move.l   (a1)+,(a0)+
   move.l   (a1)+,(a0)+
   dbra     d1,copygp3
   dbra     d0,copygp1            * naechsten Block kopieren
   movem.l  (a7)+,d0/d1/a0-a2     * Hole Register wieder vom Stack
   rts

copygp4:
   move.w   #4096-1,d1            * 64 kB werden direkt kopiert
   bsr      showgpep              * GP-EPROM einblenden
copygp5:
   move.l   (a2)+,(a0)+           * 16 Bytes kopieren
   move.l   (a2)+,(a0)+
   move.l   (a2)+,(a0)+
   move.l   (a2)+,(a0)+
   dbra     d1,copygp5
   bsr      hidegpep              * GP-EPROM ausblenden
   movem.l  (a7)+,d0/d1/a0-a2     * Hole Register wieder vom Stack
   rts

*>>>>>>     KONSTANTEN   <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

testpatt:   * Testpattern fuer die Ermittlung der RAM-Groesse
   dc.l     $aa55cc33, $9966ee11, $88224400, $ff77ddbb

PROGEND:    * Ende des Bootprogramms

cpybuf:     * Zwischenpuffer fur das Kopieren des GP-EPROMs
   ds.b     4096

   end
