;ROM - Data Technology Corporation CP/M 2.2 ROM.
;
;       +-----------------------+
;       |                       |
;       |    R O M   B O O T    |
;       |                       |
;       +-----------------------+
;
;
;
;       Version number: 2.2D
;       Version date:   March 19, 1981
;
;       Update date:    March 24, 1981
;
;                       Boots from logical unit 020h (floppy)
;                       if it is ready.  Passes logical unit number
;                       to the BOOT routine in the A register.
;
;       Update date:    June 15, 1981
;                       Modified to wait three seconds for boot
;                       LUN from keyboard.
;
;       The following code is supplied to customers who
;       purchase a hard/floppy disk system from DTC.
;       The following code is written onto track 0 sector 0
;       of the hard disk.  This routine is read into memory
;       at location 0 by the user's PROM.   This routine then
;       loads the rest of the system into memory.
;
;
;       The format of the Hard Disk Boot sectors are as follows:
;
;       Logical         Routine
;       Sector          Name
;
;         0             Boot program
;
;       1 thru 8        CCP
;
;       9 thru 22       BDOS
;
;       23 thru 32      DTC CBIOS
;
;


VERS:   EQU     22


FWA:    EQU     800H - 20H
BTFWA:  EQU     0100h






       ORG     FWA
       JMP     START-FWA

START:  LXI     B,0800h
       LXI     H,FWA+0800h

START1: DCX     H
       DCX     B
       LDAX    B
       MOV     M,A
       MOV     A,C
       ORA     B
       JNZ     START1-FWA
       JMP     BOOT

;
;
       ORG     FWA + 20H

BOOT:
       IF      I696
       MVI     A,1
       OUT     0FDh            ;disable rom

CNIN:   EQU     0               ;Console input port
CONSTS: EQU     1               ;Console status port

RBR:    EQU     2               ;Input status mask
       ENDIF

       IF      I796
       MVI     A,80h
       OUT     0EBh            ;disable rom

CNIN:   EQU     0ECh            ;Console input port
CONSTS: EQU     0EDh            ;Console status port

RBR:    EQU     2               ;Input status mask

PIT:    EQU     0DEh            ;Programmable interval timer

;       Initialize console
       MVI     A,0B6h          ;Set PIT for 9600 baud
       OUT     PIT+1
       MVI     A,8
       OUT     PIT+0
       MVI     A,0
       OUT     PIT+0
       MVI     A,04Eh          ;Setup serial port
       OUT     CONSTS
       MVI     A,037h
       OUT     CONSTS
       IN      CNIN
       ENDIF

       LXI     SP,STACK
;
       LXI     B,3000          ;wait 3 seconds
       CALL    DELAY
       IN      CONSTS
       ANI     RBR
       JZ      BOOTA           ;if no character
       IN      CNIN            ;Get character pressed
       SUI     '0'
       JM      BOOTA
       CPI     4
       JNC     BOOTA
       RRC
       RRC
       RRC
       STA     LUN
BOOTA:
       LXI     D,BTFWA
       LXI     H,CIOPB
       CALL    RDISK
       ORA     A
       JNZ     BOOTA
       MOV     A,C
       ANI     FERR
       JNZ     BOOTA
       LDA     LUN
       JMP     BTFWA
;
;
;
CIOPB:  DB      RDCMD
LUN:    DB      0
       DW      0               ;Read logical sec 0
       DB      2               ;2 sectors in case of floppy
       DB      0               ;Perform retries
;       Delay a period of time
;       Enter:  BC no. of milliseconds to delay

DELCNT: EQU     4*1000          ;4 Mhz

DELAY:  MVI     A,DELCNT/26
DLAY1:  INX     B
       DCX     B
       DCR     A
       JNZ     DLAY1
       DCX     B
       MOV     A,B
       ORA     C
       JNZ     DELAY
       RET

;       Disk I/O Routines
;
;
       IF      I696
;       E X E C

EXEC:   MVI     B,BUSY          ;Wait for not busy.
       MVI     C,BUSY and (not BUSY)
       CALL    WAITM
       RNZ


       MVI     A,SLCT          ;Alert controller
       OUT     DIO+1
EXEC1:
       MOV     C,B             ;Wait for controller busy
       CALL    WAITM
       RNZ

       MVI     A,DODTA         ;Enable data in
       OUT     DIO+1

EXEC2:  IN      DIO+2           ;Get status
       XRI     0FFh
       JM      EXEC2           ;If not requesting next byte
       ANI     CMND+DIROUT
       JNZ     EXEC3           ;If CMND or DIROUT false
       MOV     A,M
       INX     H
       OUT     DIO             ;Send byte from command buffer
       JMP     EXEC2

EXEC3:  CMP     A               ;Z:=1
       RET
;
;
;
;
;       WDISK - Output from memory buffer.
;       ENTRY:  HL = COMMAND BUFFER ADDRESS
;               DE = DATA BUFFER ADDRESS
;

WDISK:  CALL    EXEC            ;Output command
       RNZ                     ;Return if timeout
WDISK1: IN      DIO+2           ;Read status
       ORA     A
       JP      WDISK1          ;If request is present
       ANI     CMND
       JNZ     GCMPS           ;If done with transfer
       LDAX    D               ;Get the data byte
       OUT     DIO
       INX     D               ;Advance buffer address
       JMP     WDISK1
;
;
;
;
;       RDISK - Input to memory buffer.
;
;       Entry:  HL = command buffer address
;               DE = data buffer address

RDISK:  CALL    EXEC
       RNZ                     ;Return if timeout
RDISK1: IN      DIO+2           ;Read status
       ORA     A
       JP      RDISK1          ;If request is present
       ANI     CMND
       JNZ     GCMPS
       IN      DIO
       STAX    D
       INX     D
       JMP     RDISK1
;
;
;
;
;       WAITF - Wait for function to complete.

WAITF:  MVI     B,REQ+CMND      ;Wait for both REQ and CMND
       MOV     C,B
       CALL    WAITM
       RNZ
;
;       Get completion status.

GCMPS:  IN      DIO             ;Get completion status
       MOV     C,A

GCMP1:  IN      DIO+2
       ORA     A
       JP      GCMP1           ;If REQ not set

       MOV     B,A
       IN      DIO             ;Get message byte
       RET
       ENDIF
;

;
;
;
       IF      I796
;       EXEC - Output the command
;
;       Enter:  HL is the command buffer address
;               DE - data transfer address.

EXEC:
       MOV     A,E             ;Output DMA address
       OUT     DIO+2
       MOV     A,D
       OUT     DIO+3
       MOV     A,L
       OUT     DIO+4
       MOV     A,H
       OUT     DIO+5
       MVI     A,0
       OUT     DIO+6
       OUT     DIO+7
       OUT     DIO
       CMP     A               ;Z:=1
       RET


;       Disk read/write
;
;       Entry:  same as EXEC
;
RDISK:
WDISK:  CALL    EXEC
       RNZ                     ;Return if timeout

;       WAITF - Wait until transfer done
;
;       Enter:  none
;       Exit:   when transfer completed

WAITF:  MVI     B,CMDDON        ;Wait for CMDDON
       MOV     C,B
       CALL    WAITM
       RNZ                     ;Return if timeout
;

;       GCMPS - Get completion status
;
;       Enter:  none
;       Exit:   Status in C
GCMPS:  IN      DIO+1
       MOV     C,A
       RET
       ENDIF

;       WAITM - Wait for controller with timeout
;
;       Entry:  B=Status mask
;               C=Status value
;       Exit:   Z=1 if OK, else timeout with A=C=TERR
;
WAITM:
       PUSH    D               ;Save D
       PUSH    H
       LXI     H,138           ;Two minute timeout
       LXI     D,0             ;Max wait @4MHZ is 868 ms
WAITML:
       IF      I696
       IN      DIO+2
       ENDIF
       IF      I796
       IN      DIO
       ENDIF
       ANA     B               ;Mask wait bits
       CMP     C               ;Check value
       JZ      WAITM1
       DCX     D               ;Not ready.  Decrement time
       MOV     A,D
       ORA     E
       JNZ     WAITML
       DCX     H
       MOV     A,H
       ORA     L
       JNZ     WAITML
       MVI     B,0             ;Timeout
       MVI     A,TERR
       ORA     A
WAITM1:
       POP     H
       POP     D               ;Restore D
       MOV     C,A             ;Return status in C
       RET
;
       ORG     FWA + 200H
STACK:
       END