title	'Park Disk Routine for Hard Disks 5-3-85'

;
;	Hard Disk Parking Routine for MSDOS
;	Version for Seagate 20-60 meg drives, though should work for
;	any size hard disks
;
;	Currently setup for DOS and MASM
;
;	Also provides limited diagnostics (ie Drive Parameters)
;	and parks multiple drives
;
;	Author:		M. Steven Baker
;	Revision date	January 31, 1985
;	Last revision	May 3, 1985
;
;	If using MASM use exe2bin to convert to a .COM file
;	you can then load PARK.com with debug and change CX=260
;	and W (write) out the file shrinking its size 
;	This chops off the 200h bytes of stack space from the COM file
;
;	E Q U A T E S
;
cr	equ	0dh
lf	equ	0ah
;
false	equ	0
true	equ	not false	
;
CPM86	equ	false
MSDOS	equ	not CPM86

ISMASM    equ true

    if  ISMASM        ;use some Macros
jmps	macro	dummy
	jmp	short 	dummy
	endm
;
rs	macro	count
	db	count dup(?)
	endm

cseg	macro
	CODE	segment
	assume	cs:CODE,ds:CODE,es:CODE,ss:CODE
	endm

    ENDIF   ;ISMASM


;
	cseg

	ORG	0100h
;
start:	jmps	start1
dosflg:	dw	MSDOS		;0=CPM86 FF=dos
;
start1:	mov	ax,cs
	mov	ds,ax
	mov	es,ax
	mov	ss,ax
	mov	sp,offset stktop
	cld
;
	call	ilprt
	db	cr,lf,'Park version 2.01  5-3-85 (msb)',cr,lf,0
;
parkit:	mov	dx,80h
	push	dx
	call	getparms
	jnc	parm_ok
parker:	jmp	parm_err
;
parm_ok: mov	ax,dx
	pop	dx
;
	push	ax
	call	ilprt	
	db	'DRIVE PARMETERs: TotDrvs=',0
	pop	ax
	push	ax
	add	al,'0'		;AL = number of drives
	call	conout
	pop	ax
	call	crlf
;
	xor	cx,cx		;zero CX as loop counter
	mov	cl,al
	or	cx,cx		; are there any drives
	jz	nodrives
;
parklp:	push	cx		;save number of drives
	push	dx		;save drive number
	mov	ax,1100h	;recalibrate hard disk
	int	13h
	jnc	recal_ok
	jmp	recal_err
;
recal_ok:
	call	getparms
	jnc	ok_2
	jmp	parm_err
;

ok_2:	mov	ax,dx
	pop	dx		;restore drive number
	push	dx
	call	sayparms
	MOV	AX,0C00H	;seek command
	INT	13H
	jc	seek_err
;
	pop	dx
	inc	dx		; go to next drive
	pop	cx		;get back loop counter
	loop	parklp

	call	ilprt
	db	CR,LF,'Head(s) parked !!',CR,LF,0

	jmp	exit		;and terminate
;
nodrives:
	call	ilprt
	db	cr,lf,'NO HARD DISK drives installed',cr,lf,0
	jmp	exit
;
seek_err:
	call	ilprt
	db	cr,lf,'Seek error on drive ',0
	call	saydrive
	jmp	abort

recal_err:
	call	ilprt
	db	cr,lf,'Recalibrate error on drive ',0
	call	saydrive
	jmp	abort

parm_err:
	call	ilprt
	db	cr,lf,'Disk Parameter call returned error on drive ',0
	call	saydrive
	jmp	abort

saydrive:
	push	ax
	mov	al,dl		;get hard disk drive # to AL
	and	al,7fh		;strip 8th bit
	add	al,'0'
	call	conout
	pop	ax
	ret

getparms:
	mov	ax,0800h	;get current drive parameters
	int	13h
	ret

;	S A Y P A R M S
;	entry:	DL = drive number
;		AL = number of consecutive drives
;		AH = maximum useable head number		
;		CH = maximum useable value for cylinder
;		CL = maximum useable value for sector number
;			and cylinder number high bits
;	exit:	all registers preserved

sayparms:
	push	ax
	push	bx
	push	cx
	push	dx
;
	push	ax
	call	ilprt	
	db	'DRIVE PARMs:   Drv=',0
	mov	al,dl		;Drive #
	and	al,7fh		;strip off lower bits
	add	al,'0'
	call	conout		;say drive
;
	call	ilprt
	db	'  Heads=',0
	pop	ax		;restore heads and tot drives
	xchg	ah,al
	call	hexout
;
	call	ilprt
	db	'  Cyls=',0
	push	cx		;save cylinders and sectors
	mov	ax,cx
	and	ax,0c0h		;strip off high bits of CL
;
	push	cx
	mov	cx,6
shloop:	shr	ax,1
	loop	shloop
	pop	cx
;
	call	hexout
	pop	cx		;restore CX = sectors & cylinders
	mov	al,ch		;now lower 8 bits of cylinders
	call	hexout
	mov	al,'h'
	call	conout
;
	call	ilprt
	db	'  Sectors= ',0
	mov	al,cl
	and	al,3fh		;strip off lower 6 bits
	call	hexout
	mov	al,'h'
	call	conout
;
	call	crlf
;
	pop	dx
	pop	cx
	pop	bx
	pop	ax
	ret
;
conout:	push	ax
	push	bx
	push	dx
	mov	dl,al
	mov	ah,6
	int	21h		;change this to a CALL BDOS for CP/M
	pop	dx
	pop	bx
	pop	ax
	ret
;
ilprt:
	pop	si
ilprt1:	lodsb
	or	al,al
	jz	ilprtr
	call	conout
	jmps	ilprt1
ilprtr:	push	si
	ret
;
hexout:	push	ax
	shr	al,1
	shr	al,1
	shr	al,1
	shr	al,1
	call	pnib
	pop	ax
	push	ax
	call	pnib
	pop	ax
	ret
;
pnib:	and	al,0fh
	add	al,'0'
	cmp	al,'9'
	jbe	pnib2
	add	al,7
pnib2:
	call	conout
	ret

crlf:	push	ax
	mov	al,CR
	call	conout
	mov	al,LF
	call	conout
	pop	ax
	ret
abort:
	call	ilprt
	db	'  .. Aborting',cr,lf,0
exit:	mov	ax,0
	int	21h		;change to a call BDOS for CP/M
exit1:	jmps	exit1
;
	db	0

	even

;temp	equ	$ and 0fffeh		;make on even boundary for CP/M-86
;
;	org	temp
	RS	200h
stktop	dw	0
	dw	0
;
	CODE	ends
	end	start		;put starting label routine at 100h
