Added boot sector and I/O system

Added the reconstructed source code of the boot sector and I/O system (DOS BIOS).
This commit is contained in:
Broken Pipe
2024-02-15 04:44:40 +00:00
parent b5fb0df9b6
commit f98e3657d4
2 changed files with 753 additions and 0 deletions
+148
View File
@@ -0,0 +1,148 @@
;This is a disk boot routine for the 1771/1791 type disk
;controllers. It would normally reside on track 0,
;sector 1, to be loaded by the "B" command of the
;monitor at address 200H. By changing the equates
;below, it may be configured to load any size of
;program at any address. The program is assumed to
;occupy consecutive sectors starting at track 0, sector
;2, and will begin exection at its load address (which
;must be a 16-byte boundary) with the Instruction
;Pointer set to zero.
; Variations are available for the Cromemco 4FDC with
; large disks, the 4FDC with small disks, the Tarbell
; single-density controller, and the Tarbell double-
; density controller. Select one.
CROMEMCOSMALL: EQU 0
CROMEMCOLARGE: EQU 1
TARBELLSINGLE: EQU 0
TARBELLDOUBLE: EQU 0
LOAD: EQU 400H ;Address to load program
SEG: EQU 40H ;LOAD/10H
SECTOR: EQU 51 ;No. of 128-byte sectors to load
BOOTER: EQU 200H ;"B" command puts booter here
;**************************************************************
CROMEMCO: EQU CROMEMCOLARGE+CROMEMCOSMALL
TARBELL: EQU TARBELLSINGLE+TARBELLDOUBLE
WD1771: EQU CROMEMCO+TARBELLSINGLE
WD1791: EQU TARBELLDOUBLE
SMALL: EQU CROMEMCOSMALL
LARGE: EQU CROMEMCOLARGE+TARBELL
IF SMALL
MAXSECT:EQU 18
ENDIF
IF LARGE
MAXSECT:EQU 26
ENDIF
IF TARBELL
DISK: EQU 78H
ENDIF
IF CROMEMCO
DISK: EQU 30H
ENDIF
IF WD1771
READCOM:EQU 88H
ENDIF
IF WD1791
READCOM:EQU 80H
ENDIF
IF CROMEMCOLARGE
WAITBYTE:EQU 0B1H
ENDIF
IF CROMEMCOSMALL
WAITBYTE:EQU 0A1H
ENDIF
ORG BOOTER
PUT 100H
XOR AX,AX
MOV DS,AX
MOV ES,AX
MOV SS,AX
UP
MOV DI,LOAD
MOV DX,SECTOR
MOV BL,2
SECT:
MOV AL,BL
OUTB DISK+2
MOV CX,128
INB DISK+4
TEST AL,20H
MOV AL,READCOM
JNZ OUTCOM
MOV AL,READCOM+4
OUTCOM:
OUTB DISK
IF CROMEMCO
MOV AL,WAITBYTE
OUT DISK+4 ;Turn on hardware wait
ENDIF
READ:
INB DISK+4
IF TARBELL
ROL AL
JNC DONE
ENDIF
IF CROMEMCO
ROR AL
JC DONE
ENDIF
INB DISK+3
STOB
LOOP READ
GETSTAT:
INB DISK+4
IF TARBELL
ROL AL
JC GETSTAT
ENDIF
IF CROMEMCO
ROR AL
JNC GETSTAT
ENDIF
DONE:
IN DISK
AND AL,9CH
JNZ SECT
DEC DX
JZ BOOT
INC BL
CMP BL,MAXSECT+1
JNZ SECT
XOR BL,BL
INC DX
MOV AL,58H ;Step in with update
OUTB DISK
JP GETSTAT
BOOT:
MOV AX,SEG
MOV SS,AX
MOV ES,AX
MOV DS,AX
JMP 0,SEG

+605
View File
@@ -0,0 +1,605 @@
; I/O System for 86-DOS.
; Assumes a CPU Support card at F0 hex for character I/O,
; with disk drivers for Tarbell or Cromemco controllers.
; Select disk controller here
TARBELL:EQU 0
CROMEMCO:EQU 1
; For either disk controller, a custom drive table may be defined
CUSTOM: EQU 0
; If Tarbell disk controller, select one-sided or two-sided drives
; and single or double density controller
DOUB1SIDE:EQU 0
DOUB2SIDE:EQU 0
SNGL1SIDE:EQU 0
; If Cromemco disk controller, select drive configuration
SMALLCRO:EQU 0 ;3 small drives
COMBCRO:EQU 1 ;2 large drives and 1 small one
LARGECRO:EQU 0 ;4 large drives
WD1791: EQU DOUB1SIDE+DOUB2SIDE
WD1771: EQU CROMEMCO+SNGL1SIDE
IF WD1791
READCOM:EQU 80H
WRITECOM:EQU 0A0H
ENDIF
IF WD1771
READCOM:EQU 88H
WRITECOM:EQU 0A8H
ENDIF
IF TARBELL
DONEBIT:EQU 80H
DISK: EQU 78H
ENDIF
IF CROMEMCO
DONEBIT:EQU 1
DISK: EQU 30H
ENDIF
DOSSEG: EQU 80H
ORG 0
PUT 100H
BASE: EQU 0F0H
STAT: EQU BASE+7
DAV: EQU 2
TBMT: EQU 1
DATA: EQU BASE+6
PSTAT: EQU BASE+0DH
PDATA: EQU BASE+0CH
JMP INIT
JMP STATUS
JMP INP
JMP OUTP
JMP PRINT
JMP AUXIN
JMP AUXOUT
JMP READ
JMP WRITE
JMP RETL ;Flush buffers
INIT:
MOV AX,CS
MOV DS,AX
MOV SS,AX
MOV SP,STACK
MOV SI,INITTAB
CALL 0,DOSSEG
MOV DX,100H
MOV AH,26 ;Set DMA address
INT 21H
MOV BX,DS
MOV AX,CS
MOV DS,AX
MOV DX,FCB
MOV AH,15
INT 21H
OR AL,AL
JNZ COMERR
MOV [FCB+33],0
MOV CX,200H
MOV AH,39 ;Load file
INT 21H
JCXZ COMERR
CMP AL,1
JNZ COMERR
MOV DS,BX
MOV ES,BX
MOV SS,BX
MOV SP,40H
XOR AX,AX
PUSH AX
MOV DX,80H
MOV AH,26
INT 21H
PUSH BX
MOV AX,100H
PUSH AX
RET L
COMERR:
MOV DX,BADCOM
MOV AH,9 ;Print string
INT 21H
EI
STALL: JP STALL
BADCOM: DB 13,10,"Bad or missing Command Interpreter",13,10,"$"
FCB: DB 1,"COMMAND COM"
DS 24
STATUS:
IN STAT
AND AL,DAV
RET L
AUXIN:
INP:
IN STAT
AND AL,DAV
JZ INP
IN DATA
AND AL,7FH
RET L
AUXOUT:
OUTP:
PUSH AX
OUTLP:
IN STAT
AND AL,TBMT
JZ OUTLP
POP AX
OUT DATA
RET L
PRINT:
PUSH AX
PRINLP:
IN PSTAT
AND AL,TBMT
JZ PRINLP
POP AX
OUT PDATA
RET L
READ:
CALL SEEK
RDLP:
PUSH CX
CALL READSECT
POP CX
JC ERROR
INC DH
ADD SI,128
LOOP RDLP
OR AL,AL
RETL: RET L
WRITE:
CALL SEEK
WRTLP:
PUSH CX
CALL WRITESECT
POP CX
JC ERROR
INC DH
ADD SI,128
LOOP WRTLP
OR AL,AL
RET L
ERROR:
SEG CS
MOV B,[DI],-1
RET L
SEEK:
; Inputs:
; AL = Drive number
; BX = Disk transfer address in DS
; CX = Number of sectors to transfer
; DX = Logical record number of transfer
; Function:
; Seeks to proper track.
; Outputs:
; AH = Drive select byte
; DL = Track number
; DH = Sector number
; SI = Disk transfer address in DS
; DI = pointer to drive's track counter in CS
; CX unchanged.
MOV SI,BX ; Save transfer address
CBW
MOV BX,AX ; Prepare to index on drive number
SEG CS
MOV AL,[BX+DRVTAB]
OUT DISK+4 ; Select drive
IF CROMEMCO
OR AL,80H ;Set auto-wait bit
ENDIF
MOV AH,AL ;Save for later
XCHG AX,DX
MOV DL,26 ;26 sectors per track
IF CROMEMCO
TEST DH,10H ;Check if small disk
JNZ BIGONE
MOV DL,18 ;18 sectors on small disk track
BIGONE:
ENDIF
DIV AL,DL ;Compute track and sector
XCHG AX,DX
INC DH ;First sector is 1, not zero
SEG CS
MOV BL,[BX+TRKPT] ;Get this drive's displacement into track table
ADD BX,TRKTAB ;BX now points to track counter for this drive
MOV DI,BX
MOV AL,DL
SEG CS
XCHG AL,[DI] ;Xchange current track with desired track
OUT DISK+1 ;Inform controller chip of current track
CMP AL,DL
JZ ONTRK
MOV BH,3 ;Seek retry count
CMP AL,-1 ;Head position known?
JNZ NOHOME ;If not, home head
TRYSK:
CALL HOME
NOHOME:
MOV AL,DL
OUT DISK+3
MOV AL,1CH
CALL MOVHEAD
AND AL,98H
JZ ONTRK
DEC BH
JNZ TRYSK
STC
ONTRK:
RET
SETUP:
IF CROMEMCO
TEST AH,10H ;Check for small disk
JNZ CHKSTP
CMP DH,18 ;Only 18 sectors/track on small ones
JA STEP
CHKSTP:
ENDIF
CMP DH,26 ;Check for overflow onto next track
JBE PUTSEC
STEP:
INC DL
MOV DH,1
MOV AL,58H ;Step in with update, no verify
CALL DCOM
SEG CS
INC B,[DI] ;Update track counter
PUTSEC:
MOV AL,DH
OUT DISK+2
MOV CX,80H
IF TARBELL
INB DISK ;Get head load bit
ENDIF
IF CROMEMCO
INB DISK+4 ;Get head load bit
XCHG AL,AH
OUTB DISK+4 ;Turn on auto-wait
XCHG AL,AH
ENDIF
NOT AL
AND AL,20H ;Check head load status
JZ CHKDRV
MOV AL,4
CHKDRV:
; Turn on 15ms head load delay if selecting a different drive
SEG CS
CMP AH,[CURDRV]
SEG CS
MOV [CURDRV],AH
JZ RET
OR AL,4
RET
READSECT:
CALL SETUP
JC RET
MOV BL,10
RDAGN:
OR AL,READCOM
OUT DISK
PUSH SI
RLOOP:
IN DISK+4
TEST AL,DONEBIT
IF TARBELL
JZ RDONE
ENDIF
IF CROMEMCO
JNZ RDONE
ENDIF
IN DISK+3
MOV [SI],AL
INC SI
LOOP RLOOP
RDONE:
POP SI
CALL GETSTAT
AND AL,9CH
JZ RET
MOV AL,0
DEC BL
JNZ RDAGN
STC
RET
WRITESECT:
CALL SETUP
JC RET
MOV BL,10
WRTAGN:
OR AL,WRITECOM
OUT DISK
PUSH SI
WRLOOP:
IN DISK+4
TEST AL,DONEBIT
IF TARBELL
JZ WRDONE
ENDIF
IF CROMEMCO
JNZ WRDONE
ENDIF
LODB
OUT DISK+3
LOOP WRLOOP
WRDONE:
POP SI
CALL GETSTAT
AND AL,09CH
JZ RET
MOV AL,0
DEC BL
JNZ WRTAGN
STC
RET
HOME:
IF CROMEMCO
TEST AH,10H ;Check seek speed bit
JNZ RESTORE
ENDIF
MOV BL,3
TRYHOM:
MOV AL,0CH
CALL DCOM
AND AL,98H
JZ RET
MOV AL,58H ;Step in with update
CALL DCOM
DEC BL
JNZ TRYHOM
RET
MOVHEAD:
IF CROMEMCO
TEST AH,10H ;Check seek speed bit
JNZ FASTSK
ENDIF
DCOM:
OUT DISK
MOV AL,50
DELAY:
DEC AL ;Delay 10 microseconds
JNZ DELAY
GETSTAT:
IN DISK+4
TEST AL,DONEBIT
IF TARBELL
JNZ GETSTAT
ENDIF
IF CROMEMCO
JZ GETSTAT
ENDIF
IN DISK
RET
IF CROMEMCO
RESTORE:
MOV AL,0C4H ;READ ADDRESS command to keep head loaded
OUT DISK
MOV AL,77H
OUT 4
CHKRES:
IN 4
AND AL,40H
JZ RESDONE
IN DISK+4
TEST AL,DONEBIT
JZ CHKRES
IN DISK
JP RESTORE ;Reload head
RESDONE:
MOV AL,7FH
OUT 4
CALL GETSTAT
MOV AL,0
OUT DISK+1 ;Tell 1771 we're now on track 0
RET
FASTSK:
MOV AL,6FH
OUT 4
MOV AL,18H
CALL DCOM
SKWAIT:
IN 4
TEST AL,40H
JNZ SKWAIT
MOV AL,7FH
OUT 4
MOV AL,0
RET
ENDIF
DS 20H
STACK:
LFAT: EQU 300H
SFAT: EQU 200H
CURDRV: DS 1
LDRIVE:
DB 1 ;Records/sector
DB 4 ;Records/cluster
DW 52 ;Reserved records
DB 6 ;FAT size (records)
DB 2 ;Number of FATs
DB 8 ;Number of directory records
DW 482 ;Number of clusters on drive
SDRIVE:
DB 1
DB 2
DW 54
DB 4
DB 2
DB 8
DW 330
IF DOUB1SIDE
DRVTAB: DB 0,10H,20H,30H
TRKPT: DB 0,1,2,3
TRKTAB: DB -1,-1,-1,-1
ENDIF
IF DOUB2SIDE
DRVTAB: DB 0,40H,10H,50H
TRKPT: DB 0,0,1,1
TRKTAB: DB -1,-1
ENDIF
IF SNGL1SIDE
DRVTAB: DB 0F2H,0E2H,0D2H,0C0H
TRKPT: DB 0,1,2,3
TRKTAB: DB -1,-1,-1,-1
ENDIF
IF TARBELL
INITTAB:DB 4 ;Number of drives
DW LDRIVE
DW FAT0
DW LDRIVE
DW FAT1
DW LDRIVE
DW FAT2
DW LDRIVE
DW FAT3
ORG 0
FAT0: DS LFAT
FAT1: DS LFAT
FAT2: DS LFAT
FAT3: DS LFAT
ENDIF
; Cromemco drive select byte is derived as follows:
; Bit 7 = 0
; Bit 6 = 1 if fast seek (PerSci)
; Bit 5 = 1 (motor on)
; Bit 4 = 0 for 5", 1 for 8" drives
; Bit 3 = 1 for drive 3
; Bit 2 = 1 for drive 2
; Bit 1 = 1 for drive 1
; Bit 0 = 1 for drive 0
IF LARGECRO
; Table for four large drives
DRVTAB: DB 31H,32H,34H,38H
TRKPT: DB 0,0,1,1
TRKTAB: DB -1,-1
INITTAB:DB 4 ;Number of drives
DW LDRIVE
DW FAT0
DW LDRIVE
DW FAT1
DW LDRIVE
DW FAT2
DW LDRIVE
DW FAT3
ORG 0
FAT0: DS LFAT
FAT1: DS LFAT
FAT2: DS LFAT
FAT3: DS LFAT
ENDIF
IF COMBCRO
; Table for two large drives and one small one
DRVTAB: DB 31H,32H,24H
TRKPT: DB 0,0,1
TRKTAB: DB -1,-1
INITTAB:DB 3 ;Number of drives
DW LDRIVE
DW FAT0
DW LDRIVE
DW FAT1
DW SDRIVE
DW FAT2
ORG 0
FAT0: DS LFAT
FAT1: DS LFAT
FAT2: DS SFAT
ENDIF
IF SMALLCRO
; Table for 3 small drives
DRVTAB: DB 21H,22H,24H
TRKPT: DB 0,1,2
TRKTAB: DB -1,-1,-1
INITTAB:DB 3
DW SDRIVE
DW FAT0
DW SDRIVE
DW FAT1
DW SDRIVE
DW FAT2
ORG 0
FAT0: DS SFAT
FAT1: DS SFAT
FAT2: DS SFAT
ENDIF
IF CUSTOM
; Table for 2 large drives without fast seek
DRVTAB: DB 31H,32H
TRKPT: DB 0,1
TRKTAB: DB -1,-1
INITTAB:DB 2
DW LDRIVE
DW FAT0
DW LDRIVE
DW FAT1
ORG 0
FAT0: DS LFAT
FAT1: DS LFAT
ENDIF