;
;
;
;BOOT - Data Technology Corporation CP/M 2.2 BOOT.
;
;       +-----------------------+
;       |                       |
;       |       B O O T         |
;       |                       |
;       +-----------------------+
;
;
;
;       Version number: 2.2B
;       Version date:   March 19, 1981
;
;       Update date:    March 24, 1981
;
;       Update date:    June 26, 1981
;                       No longer support boot from single-density
;                       diskette.
;
;                       Boots from logical unit number in A
;                       register on entry.
;
;       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










;Enter and exit with A = logical unit # of the boot device


       ORG     100h
BOOT:
       LXI     SP,BOOT
       LXI     H,DT            ;Find parameters
       LXI     D,DTELN
       MVI     B,NLUN
BOOT2:
       CMP     M
       JZ      BOOT3
       DAD     D
       DCR     B
       JNZ     BOOT2
       LXI     H,DT
       XRA     A
BOOT3:
       INX     H
       STA     LUN             ;Set logical unit number
       STA     CIOAD+1
       STA     CIOFS+1
       MOV     A,M
       STA     CIOPB+3         ;Set starting sector
       INX     H
       MOV     A,M
       STA     CIOPB+4         ;Set # sectors
       INX     H               ;Set drive type
       MOV     A,M
       INX     H
       CPI     0FFh
       JZ      BOOT0
       STA     CIOAD+4
       PUSH    H
       LXI     H,CIOAD
       CALL    EXEC
       CZ      WAITF
       POP     H
BOOT0:
       MOV     A,M
       CPI     0FFh
       JZ      BOOT1
       STA     CIOFS+5
       LXI     H,CIOFS
       CALL    EXEC
       CZ      WAITF
BOOT1:
       LXI     D,CCP
       LXI     H,CIOPB
       CALL    RDISK
       ORA     A
       JNZ     BOOT1
       MOV     A,C
       ANI     FERR
       JNZ     BOOT1

       LDA     LUN
       JMP     CBIOS


CIOAD:  DB      ADCMD,0,0,0,0,0
CIOFS:  DB      FSCMD,0,0,0,0,0
CIOPB:  DB      RDCMD
LUN:    DB      0

       DB      0,1
       DB      0               ;Read two tracks less BOOT
       DB      0               ;Perform not retries

BOTSIZ: EQU     BIOCOD+CBIOS-CCP
HBTLN:  EQU     BOTSIZ/256
FBTLN:  EQU     24+(BOTSIZ-24*128)/256
MBTLN:  EQU     14+(BOTSIZ-14*128)/256

DT:
       IF      LUN0
       DB      0 SHL 5
       DB      1+NF0+N48M0+N96M0
       DB      NH0*HBTLN+NF0*FBTLN+(N48M0+N96M0)*MBTLN
       DB      LUN0DAT
       DB      B0
       ENDIF
       IF      LUN1
       DB      1 SHL 5
       DB      1+NF1+N48M1+N96M1
       DB      NH1*HBTLN+NF1*FBTLN+(N48M1+N96M1)*MBTLN
       DB      LUN1DAT
       DB      B1
       ENDIF
       IF      LUN2
       DB      2 SHL 5
       DB      1+NF2+N48M2+N96M2
       DB      NH2*HBTLN+NF2*FBTLN+(N48M2+N96M2)*MBTLN
       DB      LUN2DAT
       DB      B2
       ENDIF
       IF      LUN3
       DB      3 SHL 5
       DB      1+NF3+N48M3+N96M3
       DB      NH3*HBTLN+NF3*FBTLN+(N48M3+N96M3)*MBTLN
       DB      LUN3DAT
       DB      B3
       ENDIF
DTELN:  EQU     5
DTLEN:  EQU     ($-DT)/DTELN

;       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
;
;
;
;
;       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


       END