;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