          NAM BOOT ROM / 68K
          OPT PAG
          PAG

********************************************************
* 68K BOOT ROM FOR THE PERIPHERAL TECH PT-68K
*
* COPYRIGHT (C) 1986 BY PETER A. STARK
* STAR-K SOFTWARE SYSTEMS CORP.
********************************************************

* MOD. >>A<< 3-28-87 TO SLOW DOWN 1772 STEP RATE AND TO
*    RETRY HARD DISK BOOT IF THERE'S A PROBLEM
* MODIFIED 10-26-86 TO PROVIDE A BOOT MENU

* EQUATES

ROM       EQU $FFFFC000
SCRPAD    EQU $0400
MSTACK    EQU SCRPAD+$300          $0800 MON STACK

* DATA AREA FOR HARD DISK BOOT

          ORG SCRPAD
OURWIN    DS.B 14                  OUR COPY OF WIN TABLE
BUFFER    DS.B 256                 SECTOR BUFFER

* PROGRAM BEGINNING

          ORG ROM

********************************************************
* VECTORS TO GO AT THE BEGINNING OF MEMORY
********************************************************

VECTRS DC.L MSTACK                 INITIAL SUPERVISOR STACK POINTER
       DC.L COLDST                 RESET VECTOR
       DC.L BUSERR                 BUS ERROR
       DC.L ADDERR                 ADDRESS ERROR
       DC.L ILLINS                 ILLEGAL INSTRUCTION
       DC.L ZERDIV                 ZERO DIVIDE
       DC.L CHKINS                 CHK INSTRUCTION
       DC.L TRAPVI                 TRAPV INSTR
       DC.L PRIVIO                 PRIVILEGE VIOLATION
       DC.L TRARET                 TRACE
       DC.L LN1010                 LINE 1010
       DC.L LN1111                 LINE 1111
       DC.L UNASSI                 UNASSIGNED
       DC.L UNASSI                 "
       DC.L UNASSI                 "
       DC.L FORERR                 FORMAT ERROR ON 68010
       DC.L UNASSI                 UNASSIGNED
       DC.L UNASSI                 "
       DC.L UNASSI                 "
       DC.L UNASSI                 "
       DC.L UNASSI                 "
       DC.L UNASSI                 "
       DC.L UNASSI                 "
       DC.L UNASSI                 "
       DC.L SPURIO                 SPURIOUS INTERRUPT
       DC.L LVL1IA                 LEVEL 1 INTERRUPT AUTOVECTOR
       DC.L LVL2IA                 LEVEL 2 "
       DC.L LVL3IA                 LEVEL 3 "
       DC.L LVL4IA                 LEVEL 4 "
       DC.L LVL5IA                 LEVEL 5 "
       DC.L LVL6IA                 LEVEL 6 "
       DC.L LVL7IA                 LEVEL 7 "
       DC.L TRAP0V                 TRAP 0
       DC.L TRAP1V                 TRAP 1
       DC.L TRAP2V                 TRAP 2
       DC.L TRAP3V                 TRAP 3
       DC.L TRAP4V                 TRAP 4
       DC.L TRAP5V                 TRAP 5
       DC.L TRAP6V                 TRAP 6
       DC.L TRAP7V                 TRAP 7
       DC.L TRAP8V                 TRAP 8
       DC.L TRAP9V                 TRAP 9
       DC.L TRAPAV                 TRAP 10
       DC.L TRAPBV                 TRAP 11
       DC.L TRAPCV                 TRAP 12
       DC.L TRAPDV                 TRAP 13
       DC.L TRAPEV                 TRAP 14
       DC.L TRAPFV                 TRAP 15
VECTEN EQU *

*******************************************************
* INITIAL COLD START ROUTINE.
*******************************************************

* ON A COLD START, INITIALIZE PORTS, PARITY MEMORY,
* SET STACK POINTER

COLDST    MOVE.W #$2700,SR         SYSTEM, INTERRUPTS OFF
          BSR.L INIPOR             INITIALIZE PORTS
          BSR.L MEMRD              READ ALL OF MEMORY
          BSR.L PARON              TURN ON PARITY MEMORY

* MOVE VECTORS FROM ROM INTO RAM

          LEA VECTRS,A0            POINT TO VECTORS
          MOVE.L #0,A1             WHERE TO PUT THEM
          LEA VECTEN,A2            LAST ONE
VECMOV    MOVE.L (A0)+,(A1)+       MOVE ONE
          CMP.L A0,A2              DONE?
          BNE.S VECMOV             NO, DO MORE

* SIGN ON FOR USER
ASKHIM    MOVE.L #SIGNON,A4
          BSR.L PSTRNG             PRINT SIGN-ON
          BSR.L INCH               GET REPLY
          SUB.B #$30,D5            CVT FROM ASCII
          CMP.B #1,D5
          BEQ.L FLBOOT             SK*DOS FLOPPY BOOT
          CMP.B #2,D5
          BEQ.L HDBOOT             SK*DOS HARD BOOT
          CMP.B #3,D5
          BEQ.L OTHERF             OTHER FLOPPY
          CMP.B #4,D5
          BEQ.L OTHERH             OTHER HARD
          CMP.B #5,D5
          BEQ.L PARK               PARK HEADS
          BRA.S ASKHIM             REPEAT ON ERROR

*******************************************************
* PSTRNG
*******************************************************

* PSTRNG - CRLF FOLLOWED BY PDATA
PSTRNG    MOVEM.L A4,-(A7)
          MOVE.L #CRLFST,A4        POINT TO CRLF STRING
          BSR.S PDATA              PRINT IT
          MOVEM.L (A7)+,A4

PDATA     MOVEM.L D4,-(A7)
PDATA1    MOVE.B (A4)+,D4          GET CHARACTER
          CMP.B #4,D4              END?
          BEQ.S PDEXIT
          BSR.L OUTCH
          BRA.S PDATA1             AND REPEAT
PDEXIT    MOVEM.L (A7)+,D4
          RTS
CRLFST    FCB $0D,$0A,4

************************************************
* DECIN - DECIMAL INPUT ROUTINE
************************************************
*
* INPUT:     DIGITS COMING IN FROM INCH
* OUTPUT:    D5=NUMBER, ELSE RETURN TO ASKHIM IF NONE
* REGISTERS USED: A5, D5

DECIN     MOVE.L #0,D3             NO NUMBER AS YET
          MOVE.L #0,D6             CLEAR B FLAG FOR ERROR

* MAIN GET NUMBER LOOP
GETHD1    JSR INCH                 GET NEXT CHARACTER
          CMP.B #$0D,D5
          BEQ.S GETFIN             FINISHED IF CR
          SUB.B #$30,D5            CONVERT FROM ASCII
          CMP.B #9,D5
          BHI.S GETBAD             ONLY DIGITS ARE OK

* ON A VALID DIGIT, MULTIPLY D3 BY 10
* AND ADD CURRENT DIGIT
GETHD6    MOVE.L D3,D4             TEMP SAVE BINARY IN D4
          ASL.L #2,D3              4*D3
          ADD.L D4,D3              5*D3
          ASL.L #1,D3              10*D3
GETHD7    ADD.L D5,D3              ADD CURRENT DIGIT TO D3
          MOVE.B #1,D6             SET B FOR VALID NUMBER
          BRA.S GETHD1             AND GO DO NEXT DIGIT

* NORMAL EXIT AT END OF NUMBER: C=0, D6<>0, D5=ANSWER

GETFIN    MOVE.L D3,D5             RETURN RESULT IN D5
          TST.B D6                 CHECK IF THERE WAS A NUMBER
          BEQ.S GETBAD             NO, SIGNAL ERROR
          RTS

* WHEN INVALID DIGIT IS FOUND, INDICATE ERROR AND STOP

GETBAD    LEA BADMSG,A4
          BSR.L PSTRNG             PRINT 'BAD NUMBER'
          ADD.L #4,A7              REMOVE RETURN ADDRESS
          BRA.L ASKHIM             BACK TO MENU

BADMSG    FCC 'INVALID NUMBER - NOTHING DONE.',4

******************************************************
* TRAP PROCESSING
******************************************************

* BUSERR - BUS ERROR

BUSERR    LEA BUSMSG(PC),A4
          JSR PSTRNG
          JMP COLDST

* ADDERR - ADDRESS ERROR

ADDERR    LEA ADDMSG(PC),A4
          JSR PSTRNG
          JMP COLDST

* ILLINS - ILLEGAL INSTRUCTION

ILLINS    LEA ILLMSG(PC),A4
          JSR PSTRNG
          JMP COLDST

* ZERDIV - ZERO DIVIDE

ZERDIV    LEA ZERMSG(PC),A4
          JSR PSTRNG
          JMP COLDST

* CHKINS - CHK INSTRUCTION

CHKINS    LEA CHKMSG(PC),A4
          JSR PSTRNG
          JMP COLDST

* TRAPVI - TRAPV INSTR

TRAPVI    LEA TVIMSG(PC),A4
          JSR PSTRNG
          JMP COLDST

* PRIVIO - PRIVILEGE VIOLATION

PRIVIO    LEA PRIMSG(PC),A4
          JSR PSTRNG
          JMP COLDST

* TRARET - TRACE

TRARET    LEA TRAMSG(PC),A4
          JSR PSTRNG
          JMP COLDST

* LN1010 - LINE 1010

LN1010    LEA L10MSG(PC),A4
          JSR PSTRNG
          JMP COLDST

* LN1111 - LINE 1111

LN1111    LEA L11MSG(PC),A4
          JSR PSTRNG
          JMP COLDST

* UNASSI - UNASSIGNED

UNASSI    LEA UNAMSG(PC),A4
          JSR PSTRNG
          JMP COLDST

* FORERR - FORMAT ERROR ON 68010

FORERR    LEA FORMSG(PC),A4
          JSR PSTRNG
          JMP COLDST

* SPURIO - SPURIOUS INTERRUPT

SPURIO    LEA SPUMSG(PC),A4
          JSR PSTRNG
          JMP COLDST

* LVL1IA - LEVEL 1 INTERRUPT AUTOVECTOR

LVL1IA    LEA LV1MSG(PC),A4
          JSR PSTRNG
          JMP COLDST

* LVL2IA - LEVEL 2 INTERRUPT AUTOVECTOR

LVL2IA    LEA LV2MSG(PC),A4
          JSR PSTRNG
          JMP COLDST

* LVL3IA - LEVEL 3 INTERRUPT AUTOVECTOR

LVL3IA    LEA LV3MSG(PC),A4
          JSR PSTRNG
          JMP COLDST

* LVL4IA - LEVEL 4 INTERRUPT AUTOVECTOR

LVL4IA    LEA LV4MSG(PC),A4
          JSR PSTRNG
          JMP COLDST

* LVL5IA - LEVEL 5 INTERRUPT AUTOVECTOR

LVL5IA    LEA LV5MSG(PC),A4
          JSR PSTRNG
          JMP COLDST

* LVL6IA - LEVEL 6 INTERRUPT AUTOVECTOR

LVL6IA    LEA LV6MSG(PC),A4
          JSR PSTRNG
          JMP COLDST

* LVL7IA - LEVEL 7 INTERRUPT AUTOVECTOR

LVL7IA    LEA LV7MSG(PC),A4
          JSR PSTRNG
          JMP COLDST

* TRAP0V - TRAP 0

TRAP0V    LEA TR0MSG(PC),A4
          JSR PSTRNG
          JMP COLDST

* TRAP1V - TRAP 1

TRAP1V    LEA TR1MSG(PC),A4
          JSR PSTRNG
          JMP COLDST

* TRAP2V - TRAP 2

TRAP2V    LEA TR2MSG(PC),A4
          JSR PSTRNG
          JMP COLDST

* TRAP3V - TRAP 3

TRAP3V    LEA TR3MSG(PC),A4
          JSR PSTRNG
          JMP COLDST

* TRAP4V - TRAP 4

TRAP4V    LEA TR4MSG(PC),A4
          JSR PSTRNG
          JMP COLDST

* TRAP5V - TRAP 5

TRAP5V    LEA TR5MSG(PC),A4
          JSR PSTRNG
          JMP COLDST

* TRAP6V - TRAP 6

TRAP6V    LEA TR6MSG(PC),A4
          JSR PSTRNG
          JMP COLDST

* TRAP7V - TRAP 7

TRAP7V    LEA TR7MSG(PC),A4
          JSR PSTRNG
          JMP COLDST

* TRAP8V - TRAP 8

TRAP8V    LEA TR8MSG(PC),A4
          JSR PSTRNG
          JMP COLDST

* TRAP9V - TRAP 9

TRAP9V    LEA TR9MSG(PC),A4
          JSR PSTRNG
          JMP COLDST

* TRAPAV - TRAP 10

TRAPAV    LEA T10MSG(PC),A4
          JSR PSTRNG
          JMP COLDST

* TRAPBV - TRAP 11

TRAPBV    LEA T11MSG(PC),A4
          JSR PSTRNG
          JMP COLDST

* TRAPCV - TRAP 12

TRAPCV    LEA T12MSG(PC),A4
          JSR PSTRNG
          JMP COLDST

* TRAPDV - TRAP 13

TRAPDV    LEA T13MSG(PC),A4
          JSR PSTRNG
          JMP COLDST

* TRAPEV - TRAP 14

TRAPEV    LEA T14MSG(PC),A4
          JSR PSTRNG
          JMP COLDST

* TRAPFV - TRAP 15

TRAPFV    LEA T15MSG(PC),A4
          JSR PSTRNG
          JMP COLDST

*******************************************************
* TEXT STRINGS
*******************************************************

BUSMSG    FCC 'BUS ERROR',4
ADDMSG    FCC 'ADDRESS ERROR',4
ILLMSG    FCC 'ILLEGAL INSTRUCTION',4
ZERMSG    FCC 'ZERO DIVIDE',4
CHKMSG    FCC 'CHK INSTRUCTION',4
TVIMSG    FCC 'TRAPV INSTR',4
PRIMSG    FCC 'PRIVILEGE VIOLATION',4
TRAMSG    FCC 'TRACE MODE ERROR',4
L10MSG    FCC 'LINE 1010',4
L11MSG    FCC 'LINE 1111',4
UNAMSG    FCC 'UNASSIGNED',4
FORMSG    FCC 'FORMAT ERROR ON 68010',4
SPUMSG    FCC 'SPURIOUS INTERRUPT',4
LV1MSG    FCC 'LEVEL 1 INTERRUPT AUTOVECTOR',4
LV2MSG    FCC 'LEVEL 2 INTERRUPT AUTOVECTOR',4
LV3MSG    FCC 'LEVEL 3 INTERRUPT AUTOVECTOR',4
LV4MSG    FCC 'LEVEL 4 INTERRUPT AUTOVECTOR',4
LV5MSG    FCC 'LEVEL 5 INTERRUPT AUTOVECTOR',4
LV6MSG    FCC 'LEVEL 6 INTERRUPT AUTOVECTOR',4
LV7MSG    FCC 'LEVEL 7 INTERRUPT AUTOVECTOR',4
TR0MSG    FCC 'TRAP 0',4
TR1MSG    FCC 'TRAP 1',4
TR2MSG    FCC 'TRAP 2',4
TR3MSG    FCC 'TRAP 3',4
TR4MSG    FCC 'TRAP 4',4
TR5MSG    FCC 'TRAP 5',4
TR6MSG    FCC 'TRAP 6',4
TR7MSG    FCC 'TRAP 7',4
TR8MSG    FCC 'TRAP 8',4
TR9MSG    FCC 'TRAP 9',4
T10MSG    FCC 'TRAP 10',4
T11MSG    FCC 'TRAP 11',4
T12MSG    FCC 'TRAP 12',4
T13MSG    FCC 'TRAP 13',4
T14MSG    FCC 'TRAP 14',4
T15MSG    FCC 'TRAP 15',4
SIGNON    FCC '       SK*DOS / 68K BOOT ROM '
          FCB $0D,$0A
          FCC 'COPYRIGHT (C) 1986 BY PETER A. STARK'
          FCB $0D,$0A
          FCC '    STAR-K SOFTWARE SYSTEMS CORP.'
          FCB $0D,$0A
          FCB $0D,$0A
          FCC '  YOU MAY NOW'
          FCB $0D,$0A
          FCC '    1. BOOT SK*DOS FROM FLOPPY DISK'
          FCB $0D,$0A
          FCC '    2. BOOT SK*DOS FROM HARD DISK'
          FCB $0D,$0A
* NOTICE: THIS BOOT ROM CODE IS COPYRIGHT (C) 1986 BY PETER STARK.
* PERMISSION TO SUBSTITUTE THE ACTUAL DOS NAME FOR THE WORDS
* 'ANOTHER DOS' IN THE NEXT THREE LINES IS HEREBY DENIED.
          FCC '    3. BOOT ANOTHER DOS FROM FLOPPY DISK'
          FCB $0D,$0A
          FCC '    4. BOOT ANOTHER DOS FROM HARD DISK'
* NOTICE: THIS BOOT ROM CODE IS COPYRIGHT (C) 1986 BY PETER STARK.
* PERMISSION TO SUBSTITUTE THE ACTUAL DOS NAME FOR THE WORDS
* 'ANOTHER DOS' IN THE PRECEDING THREE LINES IS HEREBY DENIED.
          FCB $0D,$0A
          FCC '    5. PARK HARD DISK HEADS'
          FCB $0D,$0A
          FCC '  ENTER YOUR CHOICE (1-5): ',4
DRVMSG    FCB $0D,$0A
          FCC 'WHICH DRIVE - A OR B? ',4
CYLMSG    FCC 'ENTER CYLINDER NUMBER TO PARK AT: ',4

**********************************************************
* SYSTEM - DEPENDENT ROUTINES
**********************************************************

**********************************************************
* PARITY MEMORY ROUTINES
* NEEDED ONLY IF MEMORY CONTAINS PARITY CIRCUITRY
**********************************************************

MEMRD     RTS                      READ AND WRITE ALL OF MEMORY

PARON     RTS                      THEN TURN ON PARITY CIRCUITRY

************************
* CONSOLE I/O ROUTINES *
************************

***********************************************************
* EQUATES. THESE ROUTINES USE A 68681 DUART AT $E0000
* FOR THE PT-68K COMPUTER
***********************************************************

DUART     EQU $E0000               DUART ADDRESS
DMODEA    EQU 1                    PORT A MODE REG
DCLOCA    EQU 3                    PORT A CLOCK REG
DSTATA    EQU 3                    PORT A STATUS REG
DCOMMA    EQU 5                    PORT A COMMAND REGISTER
DDATAA    EQU 7                    PORT A DATA REGISTERS
DAUXA     EQU 9                    PORT A AUXILIARY CONTROL REG
DMODEB    EQU 17                   PORT B MODE REG
DCLOCB    EQU 19                   PORT B CLOCK REG
DSTATB    EQU 19                   PORT B STATUS REG
DCOMMB    EQU 21                   PORT B COMMAND REGISTER
DDATAB    EQU 23                   PORT B DATA REGISTERS
DAUXB     EQU 25                   PORT B AUXILIARY CONTROL REG


***********************************************************
* INITIALIZE CONSOLE AND PRINTER PORTS, AND SET BAUD RATES
***********************************************************

INIPOR    MOVE.L #DUART,A0         POINT TO DUART
          MOVE.B #$15,DCOMMB(A0)   CRB: MODE=1, ENABLE RX&TX
          MOVE.B #$5,DCOMMB(A0)    CRB: ENABLE RX & TX
          MOVE.B #$13,DMODEB(A0)   MRB1: NO RTS, NO PARITY, 8 BITS
          MOVE.B #$27,DMODEB(A0)   MRB2: RTS,1 STOP BIT
          MOVE.B #$BB,DCLOCB(A0)   CSRB: 9600 BAUD
          MOVE.B #$80,DAUXB(A0)    AUX CONTROL REG = SET 1
          MOVE.B DDATAB(A0),D0
          MOVE.B DDATAB(A0),D0     EMPTY RCVR BUFFER 3 TIMES
          MOVE.B DDATAB(A0),D0
* INITIALIZE SERIAL PORT A, FIND CORRECT BAUD RATE
BAUDAG    CLR.W D0
BAUWAI    SUB.W #1,D0              WAIT 1/2 SECOND OR SO
          BNE.S BAUWAI
          MOVE.B #$20,DCOMMA(A0)   RESET RECEIVER
          MOVE.B #$15,DCOMMA(A0)   CRA: MODE=1, ENABLE RX&TX
          MOVE.B #$5,DCOMMA(A0)    CRA: ENABLE RX & TX
          MOVE.B #$13,DMODEA(A0)   MRA1: NO RTS, NO PARITY, 8 BITS
          MOVE.B #$07,DMODEA(A0)   MRA2: NO RTS,1 STOP BIT
          MOVE.B #$88,DCLOCA(A0)   SET CSRA TO 2400 BAUD
          MOVE.B #$80,DAUXA(A0)    AUX CONTROL REG = SET 1
          MOVE.B DDATAA(A0),D0
          MOVE.B DDATAA(A0),D0     EMPTY RCVR BUFFER 3 TIMES
          MOVE.B DDATAA(A0),D0
BAUDWA    BTST.B #0,DSTATA(A0)     CHECK RX RDY BIT
          BEQ.S BAUDWA             WAIT FOR A CHARACTER
          MOVE.B DDATAA(A0),D0     GET CHARACTER
          AND.B #$7F,D0            REMOVE PARITY BIT
          LEA BAUTAB(PC),A1        POINT TO BAUD TABLE
BAULOO    MOVE.W (A1)+,D1          GET NEXT ENTRY
          CMP.B D0,D1              DOES IT MATCH?
          BEQ.S BAUDOK             YES, GOT RIGHT BAUD RATE
          CMP.B #$FF,D1            ARE WE AT END OF TABLE?
          BEQ.S BAUDAG             YES, TRY IT AGAIN
          BRA.S BAULOO             NO, CHECK NEXT BAUD RATE

BAUTAB    DC.W $BB7F               9600 BAUD
          DC.W $BB7E               ALSO 9600 BAUD
          DC.W $880D               2400 BAUD
          DC.W $6666               1200 BAUD
          DC.W $5578               600 BAUD
          DC.W $4400               300 BAUD
          DC.W $00FF               END OF TABLE

BAUDOK    LSR.W #8,D1              GET BAUD RATE CODE
          MOVE.B D1,DCLOCA(A0)     GIVE IT TO DUART
          MOVE.B DDATAA(A0),D0
          MOVE.B DDATAA(A0),D0     EMPTY RCVR BUFFER 3 TIMES
          MOVE.B DDATAA(A0),D0
          RTS

***********************************************************
* OUTPUT ON CONTROL PORT (MAIN CONSOLE)
***********************************************************

OUTCH     MOVEM.L A6,-(A7)
          LEA DUART,A6             POINT TO PORT
OUTCHE    BTST #2,DSTATA(A6)       CHECK TDRE
          BEQ.S OUTCHE             WAIT UNTIL READY
          MOVE.B D4,DDATAA(A6)     PRINT IT
          MOVEM.L (A7)+,A6
          RTS

*******************************************************
* INPUT FROM KEYBOARD
*******************************************************

INCH      MOVEM.L A6,-(A7)
          LEA DUART,A6             POINT TO PORT
INCHA     BTST #0,DSTATA(A6)       CHECK STATUS OF PORT
          BEQ.S INCHA              WAIT IF NOTHING
          MOVE.B DDATAA(A6),D5     ELSE GET CHARACTER
          AND.L #$7F,D5            REMOVE PARITY
          MOVE.B D5,D4
          BRA.S OUTCHE             ECHO TO SCREEN

*******************************************************
* BOOT SK*DOS FROM FLOPPY DISK
*******************************************************

DLATCH    EQU $E0061
* EXPLANATION OF DLATCH OPERATION:
*           BITS 0 & 1 SELECT DRIVE 0 OR 1, RESP
*           BITS 2 - 4 - NOT USED
*           BIT 5 SELECTS DENSITY (0 = DD)
*           BIT 6 - SELECTS SIDE (O = SIDE A)
*           BIT 7 - NOT USED
*
COMREG    EQU $E0081
STAREG    EQU COMREG
TRKREG    EQU $E0083
SECREG    EQU $E0085
DATREG    EQU $E0087

FLBOOT    MOVE.B #4,D3             RETRY COUNTER
          MOVE.B #$21,D4           DD, DRIVE 0
PRLOOP    MOVE.B D4,DLATCH         SELECT DRIVE, MOTOR, DENSITY
          EOR.B #$20,D4            CHANGE DENSITY FOR NEXT TRY
          BSR.L WAIT
* THE FOLLOWING IS 01 FOR 1772, 03 FOR OTHER WD FDC'S >>A<<
          MOVE.B #$01,COMREG       RESTORE, LOAD, SLOW STEP >>A<<
          BSR.L WNBUSY             WAIT UNTIL NOT BUSY
          MOVE.B #1,SECREG         SECTOR 1
          BSR.L WAIT

          MOVE.L #$0800,A5         WHERE TO LOAD THE SECTOR
* ASSUME INTERRUPTS ARE ALREADY OFF
          OR.W #$0700,SR
          LEA STAREG,A6            POINT A6 TO STATUS REG
          LEA DATREG,A4            POINT A4 TO DATA REG
          MOVE.B #$84,COMREG       READ COMMAND
          BSR WAIT                 WAIT FOR FDC TO SETTLE
          BRA.S RDLOOP             REPEAT UNTIL DONE

RDBYTE    MOVE.B (A4),(A5)+        GET DATA BYTE
RDLOOP    MOVE.B (A6),D6           CHECK STATUS
          BTST.B #1,D6             DRQ?
          BNE.S RDBYTE             YES
          BTST.B #0,D6             BUSY?
          BNE.S RDLOOP             YES, SO WAIT

          AND.B #$1C,D6            NR, RNF, CRC, OR LOST DATA?
          BEQ.S FDEXIT             EXIT NORMALLY IF NO ERROR
          SUB.B #1,D3              DECR RETRY COUNTER
          BNE.S PRLOOP             ELSE TRY AGAIN WHEN NOT DONE
BERROR    LEA EBDMSG,A4
          JSR PSTRNG               THEN PRINT ERROR MESSAGE
          JMP ASKHIM               AND QUIT
FDEXIT    JMP $0800                GO TO SUPER-BOOT
EBDMSG    FCC 'ERROR BOOTING SK*DOS.',4

* WAIT - WAIT ROUTINE TO WAIT A WHILE

WAIT      BSR.S WAIT4
          NOP
WAIT4     BSR.S WAIT2
          NOP
WAIT2     BSR.S WAIT1
          NOP
WAIT1     RTS                      RTS

* WNBUSY

WNBUSY    BSR.S WAIT               WAIT FOR COMMAND TO SETTLE
          MOVE.B STAREG,D6         GET STATUS
          BTST.B #0,D6             CHECK BUSY FLAG
          BNE.S WNBUSY             WAIT IF STILL BUSY
          RTS                      ELSE RETURN WITH B=STATUS

********************************************************
* BOOT SK*DOS FROM HARD DISK
********************************************************

* SK*DOS EQUATES

DRUSED    EQU $113C                DRIVE USED TABLE

WDREAD    EQU $E0020               READ DATA REGISTER
WDWRIT    EQU WDREAD               WRITE DATA REGISTER
WDERRO    EQU $E0024               ERROR REGISTER
WDWPRE    EQU WDERRO               WRITE PRECOMP REGISTER
WDSCNT    EQU $E0028               SECTOR COUNT REGISTER
WDSNUM    EQU $E002C               SECTOR NUMBER
WDCYLO    EQU $E0030               CYLINDER NUMBER - LOW ORDER BYTE
WDCYHI    EQU $E0034               CYLINDER NUMBER - HIGH ORDER BYTE
WDSDHR    EQU $E0038               SIZE,DRIVE,HEAD REGISTER
WDSTAT    EQU $E003C               STATUS REG - READ ONLY
WDCOMA    EQU WDSTAT               COMMAND REG - WRITE ONLY

* FIRST, TEST WHETHER THERE IS A WD1002

HDBOOT    MOVE.B #$A5,WDSNUM       TRY STORING INTO WD1002
          MOVE.L WDSNUM,D5         READ BACK
          CMP.L #$A5A5A5A5,D5      CHECK IT
          BNE.L BERROR             NO WD1002 THERE
          MOVE.B #$5A,WDSNUM       THEN TRY THE COMPLEMENT
          MOVE.L WDSNUM,D5         READ BACK
          CMP.L #$5A5A5A5A,D5      CHECK IT
          BNE.L BERROR             NO WD1002 THERE

* INITIALIZE THE WINCHESTER

          MOVE.B #$88,WDSDHR       ECC,SEC=256,DRIVE 1,HEAD 0
          MOVE.B #32,WDWPRE        SET PRECOMP TO TRACK 128
          MOVE.B #$1F,WDCOMA       DO A SLOW RESTORE
          BSR.L CHBUSY             WAIT FOR WD1002 NOT BUSY
          BNE.L BERROR             EXIT IF ERROR

* READ TRACK 0 SECTOR 0 TO DETERMINE PARTITION 0 LAYOUT

          MOVE.B #0,WDSNUM         SECTOR 0
          MOVE.B #0,WDCYHI
          MOVE.B #0,WDCYLO         CYLINDER 0
          MOVE.B #1,WDSCNT         SECTOR COUNT = 1
          MOVE.B #$20,WDCOMA       SEND READ COMMAND
          BSR.L CHBUSY             WAIT FOR COMPLETION
          BNE.L BERROR             EXIT IF ERROR
          LEA OURWIN,A1            POINT TO OUR WINTAB
          MOVE.L WDREAD,(A1)+
          MOVE.L WDREAD,(A1)+      READ 14 BYTES OF CONFIG DATA
          MOVE.L WDREAD,(A1)+
          MOVE.W WDREAD,(A1)+
          MOVE.B WDSTAT,D7         GET WD STATUS BYTE
          BTST.B #0,D7             CHECK ERROR BIT
          BNE.L BERROR             EXIT IF ERROR

* NOW SEARCH DISK DIRECTORY FOR SK*DOS.SYS

          MOVE.L #$0005,D0         DIRECTORY START DISK ADDRESS
          LEA OURWIN,A1            POINT TO OUR WINTAB
DIREAD    LEA BUFFER,A0            DIRECTORY SECTOR BUFFER
          BSR.L HREAD              READ DIRECTORY SECTOR
          BNE.L BERROR
          LEA BUFFER,A0            BACK TO DIRECTORY BUFFER
          LEA 256(A0),A6           END OF BUFFER
          LEA 16(A0),A0            FIRST DIR ENTRY
DIRLOO    TST.B (A0)               CHECK FIRST BYTE OF ENTRY
          BMI.S NXTDIR             DELETED ENTRY
          BEQ.L BERROR             END OF DIRECTORY
          MOVE.L (A0),D7           FIRST FOUR LETTERS
          CMP.L #$534B2A44,D7      "SK*D" ?
          BNE.S NXTDIR             NO
          MOVE.L 4(A0),D7          NEXT FOUR LETTERS
          CMP.L #$4F530000,D7      "OS.." ?
          BNE.S NXTDIR
          MOVE.L 8(A0),D7          NEXT THREE
          AND.L #$FFFFFF00,D7      BLANK OUT LAST
          CMP.L #$53595300,D7      "SYS" ?
          BEQ.S GOTIT              GOT IT?

NXTDIR    ADD.L #24,A0             POINT TO NEXT ENTRY
          CMP.L A0,A6              AT END OF SECTOR?
          BNE.S DIRLOO             NO, CONTINUE

          MOVE.W BUFFER,D0         AT END, GET POINTER TO NEXT
          BEQ.L BERROR             SK*DOS.SYS NOT FOUND IF AT END
          BRA.S DIREAD             ELSE LOOK AT NEXT SCTR

* WE HAVE FOUND 'SK*DOS.SYS'

GOTIT     MOVE.B 13(A0),D0
          LSL.W #8,D0
          MOVE.B 14(A0),D0         GET STARTING DISK ADDRESS
          LEA BUFFER,A0            POINT BACK TO BUFFER
          MOVE.W D0,(A0)           PUT FIRST ADDRESS INTO IT

* NOW READ THE FILE INTO MEMORY WITHOUT AN OFFSET

          MOVE.L #0,A3             ERASE EXECUTION ADDRESS
          CLR.L D1                 DATA POINTER =0
GET2      BSR.L GETNEW             GET FLAG BYTE
          CMP.B #$02,D5            IS IT 02?
          BEQ.S GETD2O             2-BYTE ADDRESS DATA
          CMP.B #$03,D5            IS IT 03?
          BEQ.S GETD4O             4-BYTE ADDRESS DATA
          CMP.B #$16,D5            IS IT 16?
          BEQ.L GETT2O             2-BYTE TRANSFER
          CMP.B #$17,D5            IS IT 17?
          BEQ.L GETT4O             4-BYTE TRANSFER
          BRA.S GET2               ANYTHING ELSE JUST SKIP

GETD2O    BSR.L GETWRD             GET 2-BYTE LOAD ADDRESS
          MOVE.L D4,A2             PUT INTO A2
          BSR.L GETNEW             GET LENGTH
          MOVE.L D5,D2             SET UP AS COUNTER
          BRA.S GETLOO             THEN CONTINUE

GETD4O    BSR.L GETWRD             GET LEFT WORD OF LOAD ADDRESS
          SWAP D4
          MOVE.L D4,A2             MOVE INTO A2
          BSR.L GETWRD             GET RIGHT WORD OF LOAD ADDRESS
          ADD.L D4,A2              COMBINE TWO WORDS
          BSR.L GETWRD             GET LENGTH
          MOVE.L D4,D2             SET UP AS COUNTER

GETLOO    BSR.L GETNEW             ELSE GET ONE BYTE
          MOVE.B D5,(A2)+          STORE IN MEMORY
          SUB.W #01,D2             DECREMENT COUNTER
          BNE.S GETLOO
          BRA.L GET2               AT END, LOOK FOR NEXT FLAG

GETT4O    BSR.S GETWRD             GET LEFT WORD OF TRANSFER ADDRESS
          SWAP D4                  MOVE INTO LEFT HALF
          MOVE.L D4,A3             SAVE IN A3
          BSR.S GETWRD             GET RIGHT HALF OF ADDR
          ADD.L A3,D4              ADD BACK TOGETHER
          MOVE.L D4,A3             SAVE EXECUTION ADDRESS
          BRA.S GET2

GETT2O    BSR.S GETWRD             GET TRANSFER ADDRESS FROM FILE
          MOVE.L D4,A3             STORE EXECUTION ADDRESS
          BRA.L GET2               AND REPEAT

* GETWRD - GET TWO-BYTE WORD FROM FILE

GETWRD    BSR.S GETNEW             GET MSB BYTE
          MOVE.L D5,D4             SAVE IN D4
          LSL.W #8,D4              MOVE INTO SECOND BYTE
          BSR.S GETNEW             GET LSB
          ADD.W D5,D4              ADD THE TWO BYTES TOGETHER IN D4
GETEXI    RTS

* GETNEW - GET BYTE FROM FILE

GETNEW    TST.B D1                 CHECK POINTER TO DATA
          BEQ.S READIT             ZERO MEANS HAVE TO READ SCTR
GETNW1    CLR.L D5
          MOVE.B (A0,D1.W),D5      READ A BYTE
          ADD.B #1,D1              POINT TO NEXT
          RTS

* READIT - READ A NEW SECTOR FROM HARD DISK INTO BUFFER

READIT    LEA BUFFER,A0            POINT TO BUFFER
          MOVE.W (A0),D0           POINTER TO NEXT
          BEQ.S FINISH             FINISHED IF 00 POINTER
          BSR.S HREAD              READ NEXT SECTOR
          MOVE.W #4,D1             POINT TO ITS FIRST BYTE
          BRA.S GETNW1             THEN CONTINUE AS ABOVE

* FINISH - WHEN FINISHED READING, JUMP TO PROGRAM IF THERE IS
* A TRANSFER ADDRESS

FINISH    MOVE.L A3,D7             TRANSFER ADDRESS, IF ANY
          BEQ.L BERROR             ERROR IF NONE
          MOVE.B #$20,DRUSED       HARD DISK BECOMES DRIVE 0
          MOVE.B #$10,DRUSED+1     FLOPPY DISK BECOMES DRIVE 1
          JMP.L (A3)               AND JUMP TO SK*DOS

* HREAD - READ SECTOR INTO MEMORY. ENTER WITH D0=LOGICAL TR/SEC,
* AND A0 = ADDRESS OF BUFFER TO READ INTO

HREAD     BSR.S LPCONV             CONVERT LOG TO PHYS ADDRESS
          MOVE.B #1,WDSCNT         SECTOR COUNT = 1
          MOVE.B #$20,WDCOMA       SEND READ COMMAND
          BSR.S CHBUSY             WAIT FOR COMPLETION
          BEQ.S HREDOK             >>A<<
          MOVE.B #$20,WDCOMA       >>A<<
          BSR.S CHBUSY             TRY AGAIN ON PROBLEM >>A<<
          BEQ.S HREDOK             >>A<<
          MOVE.B #$20,WDCOMA       >>A<<
          BSR.S CHBUSY             TRY AGAIN ON PROBLEM >>A<<
          BEQ.S HREDOK             >>A<<
          MOVE.B #$20,WDCOMA       >>A<<
          BSR.S CHBUSY             TRY AGAIN ON PROBLEM >>A<<
          BEQ.S HREDOK             >>A<<
          MOVE.B #$20,WDCOMA       >>A<<
          BSR.S CHBUSY             TRY AGAIN ON PROBLEM >>A<<
HREDOK    MOVE.L A0,A5             POINT TO BUFFER >>A<<
          MOVE.W #63,D6            COUNTER = 256/4-1
HRDLOO    MOVE.L WDREAD,(A5)+      READ 4 BYTES
          DBRA D6,HRDLOO           REPEAT FOR 256 BYTES
          BSR.S CHBUSY             WAIT FOR COMPLETION
          BNE.L BERROR             IF ERROR
          RTS

* CHBUSY - WAIT IF BUSY, BUT ABORT IF IT TAKES TOO LONG

CHBUSY    MOVE.L #$100000,D6       TIMEOUT COUNTER
CHBUS1    SUB.L #1,D6              DROP TIMEOUT COUNT
          BEQ.L BERROR             SOMETHING WRONG?
          TST.B WDSTAT             CHECK WD1002 STATUS
          BMI.S CHBUS1             WAIT UNTIL NOT BUSY
          MOVE.B WDSTAT,D7         GET WD STATUS BYTE
          BTST.B #0,D7             CHECK ERROR BIT
          RTS

* LPCONV - CONVERT A LOGICAL TRACK AND SECTOR NUMBER (IN D0
* AS 0000TRSE) INTO PHYSICAL TRACK, HEAD, AND SECTOR NUMBERS AND
* PUT INTO WD REGS, USING INFO IN OURWIN ENTRY POINTED TO BY A1

LPCONV    MOVE.W D0,D6
          LSR.W #8,D6              LOGICAL TRACK
          CLR.L D7
          MOVE.B 11(A1),D7         LOG SECT/TRACK
          ADD.B #1,D7              NUMBER PER TRACK
          MULU D7,D6               SECT BEFORE THIS TRACK
          CLR.L D7
          MOVE.B D0,D7             LOG SECTOR
          ADD.W D7,D6              BLOCK NUMBER
          MOVE.W 4(A1),D7          SECT/CYL ON HARD DISK
          DIVU D7,D6               REMAINDER | TRACK NUMBER
          ADD.W 8(A1),D6           PLUS START OF PARTITION
          MOVE.B D6,WDCYLO
          LSR.L #8,D6
          MOVE.B D6,WDCYHI         CYLINDER NUMBER TO WD1002
          LSR.L #8,D6              REMAINDER IN RIGHT HALF
          CLR.L D7
          MOVE.B 2(A1),D7          SECTORS PER TRACK
          DIVU D7,D6               SECTOR | HEAD
          ADD.B #$88,D6            COMBINE WITH OTHER SDH BITS
          MOVE.B D6,WDSDHR         PUT INTO SDH REGISTER
          SWAP D6                  MOVE SECTOR RIGHT
          MOVE.B D6,WDSNUM         SECTOR NUMBER TO WD1002
          RTS

********************************************************
* PARK HEADS ON SPECIFIED CYLINDER
********************************************************

PARK      LEA DRVMSG(PC),A4
          BSR.L PSTRNG             ASK WHICH DRIVE
          BSR.L INCH               GET ANSWER
          AND.B #$DF,D5            CVT TO UPPER CASE
          CMP.B #$41,D5            A?
          BEQ.S DRA                YES
          CMP.B #$42,D5            B?
          BEQ.S DRB                YES
          BRA.L ASKHIM             NEITHER - ABORT

DRA       MOVE.B #$88,D0           SDH CODE FOR DRIVE A
          BRA.S PARK1              AND CONTINUE
DRB       MOVE.B #$90,D0           SDH CODE FOR DRIVE B

PARK1     LEA CYLMSG(PC),A4
          BSR.L PSTRNG             ASK FOR TRACK NUMBER
          BSR.L DECIN              GET IT

          MOVE.B D5,WDCYLO         GIVE CYLINDER TO WD
          LSR.W #8,D5
          MOVE.B D5,WDCYHI         DITTO
          MOVE.B D0,WDSDHR         SELECT DRIVE
          MOVE.B #$7F,WDCOMA       SLOW SEEK TO CYLINDER
          BSR.S CHBUS              WAIT UNTIL FINISHED
          CLR.B WDSDHR             DESELECT DRIVE
          BRA.L ASKHIM             AND BACK TO MENU


* CHBUS  - WAIT IF BUSY, BUT ABORT IF IT TAKES TOO LONG

CHBUS     MOVE.L #$100000,D6       TIMEOUT COUNTER
CHBUS3    SUB.L #1,D6              DROP TIMEOUT COUNT
          BEQ.S CHBUS2             SOMETHING WRONG?
          TST.B WDSTAT             CHECK WD1002 STATUS
          BMI.S CHBUS3             WAIT UNTIL NOT BUSY
          RTS

CHBUS2    LEA RESMSG(PC),A4
          BSR.L PSTRNG             PRINT "HARDWARE PROBLEM
          RTS

RESMSG    FCC 'HARDWARE PROBLEM - PARKING ABORTED.',4

********************************************************
* BOOT OTHER FROM FLOPPY DISK
********************************************************

* NO SUCH COMMAND EXISTS RIGHT NOW, SO WE RETURN TO MENU
OTHERF    BRA.L ASKHIM

********************************************************
* BOOT OTHER FROM HARD DISK
********************************************************

* NO SUCH COMMAND EXISTS RIGHT NOW, SO WE RETURN TO MENU
OTHERH    BRA.L ASKHIM


          END
