dskcntl.asm



    name dskcntrl
    page 55,80
    title 'DSKCNTRL.ASM -- Turn hard disk on/off'
 ;
 ;  Synpet Personal Technologies, Inc.
 ;  7225 Franklin Rd, Boise, ID 83709
 ;
 ;  Created 1/28/90 - LRE
 ;
 ;
 ;
 ;  Turn hard disk off after n seconds of inactivity.  Turn back on if 
 ;  disk bios call occurs.  
 ;  The following disk control functions are available by doing a FAR
 ;  call to the dsk_prog_cntrl procedure.
 ;  Call with the number of the function desired in the ah register.
 ;  Returns 0 in register al if successful.  Returns 0ffh in al if
 ;  called with an invalid function number.  Returns 0feh in al if
 ;  called with other than the install function when dskcntrl has not
 ;  been installed yet, or is currently uninstalled.
 ;
 ;  Function 0 - Turn off disk control.  Turns on the disk if currently
 ;               off.  Disables the time out function, leaving the disk
 ;               on.
 ;  Function 1 - Turn on disk control.  Enables the disk time out function
 ;               if previously turned off.  A NOP function if called 
 ;               while diskcontrol is on.  
 ;  Function 2 - Turn off disk. - Unconditionally turns off disk, even 
 ;               if time out has not occurred, or disk control is off.  
 ;               Any disk access after this command is executed will 
 ;               still turn on the disk.
 ;  Function 3 - Turn on disk. - Unconditionally turns on disk.  If disk
 ;               control is on, restarts time out.
 ;  Function 4 - Change disk time out.  Enter with the bx register holding
 ;               the new time out value as int(seconds * 18.2).
 ;  Function 5 - Install disk control.  Starts the disk control functions
 ;               running by chaining to the BIOS timer tic and to the 
 ;               BIOS disk control interrupt.
 ;  Function 6 - Uninstall disk control.  Restores the BIOS interrupts to
 ;               their previous vectors.  MUST be called before any  
 ;               program using disk control exits, or the computer will
 ;               crash.


    disk_port_add    equ    0302h  ;
    disk_stop_byte   equ    01h    ;
    disk_start_byte  equ    00h    ;
    disk_def_time_out    equ    1092   ; Seconds times 18.2.
    disk_spin_up_time equ   1092   ;

cseg       segment      para  public  'CODE'


           assume       cs:cseg,ds:cseg,es:cseg,ss:cseg
           public       dsk_prog_cntrl


 ; Disk control variables.

 time_tic_chain_add  dd  0 ;
 disk_int_chain_add  dd  0 ;
 dsk_cntrl_seg       dw  0 ;
 disk_time_out       dw  disk_def_time_out ;
 disk_tic      dw   0    ;
 disk_spin_up_tic dw  0  ;
 disk_stopped  db   0    ;
 control_off   db   0    ;
 installed_flag db  0    ;


timer_tic  proc         far 

    pushf      ; 
    push   ax  ;
    mov    al,cs:control_off ;
    or     al,al ;
    jnz    no_disk_tic_inc ;
    cmp    cs:disk_spin_up_tic,disk_spin_up_time  ;
    je     no_spin_up_tic_inc  ;
    inc    cs:disk_spin_up_tic      ;
 no_spin_up_tic_inc:
    mov    ax,cs:disk_time_out ;
    cmp    cs:disk_tic,ax ;
    je     no_disk_tic_inc  ;
    inc    cs:disk_tic      ;
    cmp    cs:disk_tic,ax ;
    jne    no_disk_tic_inc ;
    push   dx   ;
    mov    dx,disk_port_add ;
    mov    al,disk_stop_byte ;
    out    dx,al ;
    mov    cs:disk_stopped,0ffh ;
    pop    dx   ;
 no_disk_tic_inc:
    pop    ax  ;
    popf       ;
    jmp    cs:time_tic_chain_add  ;


timer_tic  endp

disk_int_tic   proc        far

    pushf      ; 
    push   ax  ;
    mov    cs:disk_tic,0 ;
    cmp    cs:disk_stopped,0 ;
    jz     disk_is_on  ;
 disk_is_stopped:
    call   startup_disk ;
 disk_is_on:
    pop    ax  ;
    popf       ;
    jmp    cs:disk_int_chain_add  ;
     
disk_int_tic  endp

startup_disk  proc   near

    push   ax  ;
    push   bx  ;
    push   cx  ;
    push   dx  ;
    push   si  ;
    push   di  ;
    push   bp  ;
    push   ds  ;
    push   es  ;
    mov    dx,disk_port_add  ;
    mov    al,disk_start_byte ;
    out    dx,al ;
    mov    cs:disk_stopped,0 ;
    mov    cs:disk_spin_up_tic,0 ;
    sti        ;
 try_spinup:
    mov    ah,0 ;
    int    63h  ;
    mov    ah,1 ;
    int    63h  ;
    and    al,al ;
    jz     done_with_spinup ;
    cmp    cs:disk_spin_up_tic,disk_spin_up_time ;  
    jnc    done_with_spinup ;
    jmp    try_spinup ;
 done_with_spinup:
    mov    cs:disk_spin_up_tic,disk_spin_up_time  ;
    pop    es  ;
    pop    ds  ;
    pop    bp  ;
    pop    di  ;
    pop    si  ;
    pop    dx  ;
    pop    cx  ;
    pop    bx  ;
    pop    ax  ;
    ret        ;

startup_disk    endp


dsk_prog_cntrl  proc     far 

    cmp    ah,5  ;
    jz     do_init_dsk_cntrl ;
    push   ax  ;
    mov    al,cs:installed_flag ;
    or     al,al ;
    pop    ax  ;
    jz     uninstalled_error ;
    cmp    ah,0 ;
    jz     turn_off_dsk_cntrl ;
    cmp    ah,1 ;
    jz     turn_on_dsk_cntrl ;
    cmp    ah,2  ;
    jz     turn_off_dsk ;
    cmp    ah,3  ;
    jz     turn_on_dsk ;
    cmp    ah,4  ;
    jz     change_dsk_time_out ;
    cmp    ah,6  ;
    jz     do_uninstall_dsk_cntrl ;
    mov    al,0ffh ;
    ret   ;

 uninstalled_error:
    mov    al,0feh ;
    ret     ;

 turn_off_dsk_cntrl:
    mov    cs:control_off,0ffh ;
 turn_on_dsk:
    mov    cs:disk_tic,0 ;
    cmp    cs:disk_stopped,0 ;
    jz     dsk_already_on ;
    call   startup_disk ;
 dsk_already_on:
    xor    al,al ;
    ret    ;

 turn_on_dsk_cntrl:
    mov    cs:control_off,0   ;
    xor    al,al ;
    ret    ;
 
 turn_off_dsk:
    push   dx   ;
    mov    dx,disk_port_add ;
    mov    al,disk_stop_byte ;
    out    dx,al ;
    mov    cs:disk_stopped,0ffh ;
    pop    dx   ;
    xor    al,al ;
    ret     ;

 change_dsk_time_out:
    mov    cs:disk_tic,0 ;
    mov    cs:disk_time_out,bx ;
    xor    al,al ;
    ret     ;

 do_init_dsk_cntrl:
    call   init_dsk_cntrl ;
    ret     ;

 do_uninstall_dsk_cntrl:
    call   uninstall_dsk_cntrl ;
    ret     ;

dsk_prog_cntrl  endp



init_dsk_cntrl proc     near 

          ; Set timer tic address & chain address to old.
    mov    al,cs:installed_flag ;
    or     al,al ;
    jz     install ;
    xor    al,al ;
    ret      ;
 install:
    push   ds  ;
    mov    cs:disk_tic,0 ;
    mov    ax,351ch    ;
    int    21h         ;
    mov    cs:word ptr time_tic_chain_add,bx  ;
    mov    cs:word ptr time_tic_chain_add + 2,es ;
    push   cs     ;
    pop    ds     ;
    mov    dx,offset timer_tic  ;
    mov    ax,251ch    ;
    int    21h     ;
           ; Set bios disk int address & chain address to old.
    mov    ax,3513h    ;
    int    21h         ;
    mov    cs:word ptr disk_int_chain_add,bx  ;
    mov    cs:word ptr disk_int_chain_add + 2,es ;
           ; Set bios disk int address we can use.
    push   es ;
    pop    ds ;
    push   bx ;
    pop    dx ;
    mov    ax,2563h ;
    int    21h ;
    push   cs     ;
    pop    ds     ;
    mov    dx,offset disk_int_tic ;
    mov    ax,2513h    ;
    int    21h     ;
    pop    ds ;
    mov    cs:installed_flag,0ffh ;
    xor    al,al ;
    ret     ;

init_dsk_cntrl       endp


uninstall_dsk_cntrl   proc   near

      ; Restore timer int.
    push   ds ;
    mov    cs:disk_tic,0 ;
    cmp    cs:disk_stopped,0 ;
    jz     uninstall_dsk_already_on ;
    call   startup_disk ;
 uninstall_dsk_already_on:
    mov    dx,cs:word ptr time_tic_chain_add + 2 ;
    mov    ds,dx ;
    mov    dx,cs:word ptr time_tic_chain_add ;
    mov    ax,251ch ;
    int    21h  ;
    mov    dx,cs:word ptr disk_int_chain_add + 2 ;
    mov    ds,dx ;
    mov    dx,cs:word ptr disk_int_chain_add ;
    mov    ax,2513h ;
    int    21h ;
    pop    ds ;
    mov    cs:installed_flag,0 ;
    xor    al,al ;
    ret      ;

 uninstall_dsk_cntrl  endp


cseg       ends

           end