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
