86-DOS 0.2

86-DOS 0.2
Version of 86-DOS
Placeholder.png
Version0.2
Compiled1980-10
Replaces
86-DOS 0.11
Replaced by
86-DOS 0.30

86-DOS 0.2 is the third known version of 86-DOS. Its actual version number is shrouded in mystery. It has never been mentioned in official 86-DOS documents, and only the existence of an operating system between 86-DOS 0.11 and 86-DOS 0.30 is known.[1][2][3] The assumed version number – 0.2 – isn't certain. Though a version between 0.1 and 0.3 is probably 0.2, the version number could have been anything from 0.12 to 0.29.

It is worth noting that almost all utilities of 86-DOS 0.34 has the version number 0.2. It is highly likely that they started versioning utilities from 0.2, as the 86-DOS 0.11 utilities did not have version numbers. Utilities are often known to have slightly lower version numbers compared to the DOS kernel, as they are updated less often.

This version had preliminary documentation created for it, but it was never released to the general public and only appeared as an exhibit in a 1986 lawsuit between Seattle Computer Products and Microsoft.[4] Tim Paterson later scanned the documentation and uploaded it to his website.

Dumped sections[edit | edit source]

The preliminary manual includes version 0.2's BOOT.ASM and DOSIO.ASM files.[5]

BOOT.ASM

;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
DONEBIT:EQU	80H
DISK:	EQU	78H
	ENDIF

	IF	CROMEMCO
DONEBIT:EQU	1
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
	MOV	SP,BOOTER	;For debugging purposes
	UP
	MOV	DI,LOAD
	MOV	DX,SECTOR
	MOV	BL,2
SECT:
	MOV	AL,0D0H		;Force Interrupt command
	OUT	DISK		;To force Type I status
	AAM
	CMP	BL,MAXSECT+1
	JNZ	NOSTEP
	MOV	AL,58H		;Step in with update
	CALL	DCOM
	MOV	BL,1
NOSTEP:
	MOV	AL,BL
	OUTB	DISK+2

	IF	CROMEMCO
	MOV	AL,WAITBYTE
	OUT	DISK+4		;Turn on hardware wait
	ENDIF

	INB	DISK		;Get head load status
	NOT	AL
	AND	AL,20H
	JZ	OUTCOM
	MOV	AL,4
OUTCOM:
	OR	AL,READCOM
	OUTB	DISK
	MOV	CX,128
	PUSH	DI
READ:
	INB	DISK+4
	TEST	AL,DONEBIT

	IF	TARBELL
	JZ	DONE
	ENDIF

	IF	CROMEMCO
	JNZ	DONE
	ENDIF

	INB	DISK+3
	STOB
	LOOP	READ
DONE:
	POP	DI
	CALL	GETSTAT
	AND	AL,9CH
	JNZ	SECT
	ADD	DI,128
	INC	BL
	DEC	DX
	JNZ	SECT
	JMP	0,SEG

DCOM:
	OUT	DISK
	AAM
GETSTAT:
	INB	DISK+4
	TEST	AL,DONEBIT

	IF	TARBELL
	JNZ	GETSTAT
	ENDIF

	IF	CROMEMCO
	JZ	GETSTAT
	ENDIF

	IN	DISK
	RET

DOSIO.ASM

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

; 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	0		;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
	JC	ERROR
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
	JC	ERROR
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:
	MOV	AL,0D0H		;Force Interrupt command
	OUT	DISK		;so Type I status will be available
	PUSH	AX
	AAM			;Pause 10 microseconds
	POP	AX

	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

	IF	CROMEMCO
	MOV	AL,AH
	OUT	DISK+4		;Turn on auto-wait
	ENDIF

	IN	DISK		;Get head load bit
	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
	MOV	AL,4
	RET

READSECT:
	CALL	SETUP
	MOV	BL,10
RDAGN:
	OR	AL,READCOM
	OUT	DISK
	MOV	CX,80H
	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
	MOV	BL,10
WRTAGN:
	OR	AL,WRITECOM
	OUT	DISK
	MOV	CX,80H
	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,0FCH
	JZ	RET
	MOV	AL,0
	DEC	BL
	JNZ	WRTAGN
	STC
	RET

HOME:
	IF	CROMEMCO
	TEST	AH,40H		;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,40H		;Check seek speed bit
	JNZ	FASTSK
	ENDIF

DCOM:
	OUT	DISK
	PUSH	AX
	AAM			;Delay 10 microseconds
	POP	AX
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	325

	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	71H,72H,74H,78H
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	71H,72H,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

Compared to the same files (reconstructed) from 86-DOS 0.11, there are several differences. BOOT.ASM was completely rewritten, to improve reliability and allow debugging using SCP's 8086 Monitor. DOSIO.ASM has additional error checks and removed the requirement of PerSci drives for using 8" diskettes with the Cromemco 4FDC controller. The total number of usable clusters for 5.25" 90K floppy disks is now the correct value – 325.

References[edit | edit source]

  1. Seattle Computer Products (August 1980). BYTE Ad. BYTE Magazine. p. 173.
  2. Paterson, Tim (June 1983). A Short History of MS-DOS. BYTE Magazine. p. 246.
  3. Hunter, David (March 1983). The Roots of DOS: Tim Paterson. Softalk for the IBM Personal Computer. p. 12-15.
  4. Paterson, Tim (2005). 86-DOS Manuals. PatersonTech.
  5. Paterson, Tim (October 1980). 86-DOS Preliminary Instruction Manual. PatersonTech.