;*DDK*************************************************************************/
;
; COPYRIGHT    Copyright (C) 1995 IBM Corporation
;
;    The following IBM OS/2 WARP source code is provided to you solely for
;    the purpose of assisting you in your development of OS/2 WARP device
;    drivers. You may use this code in accordance with the IBM License
;    Agreement provided in the IBM Device Driver Source Kit for OS/2. This
;    Copyright statement may not be removed.;
;*****************************************************************************/
;/****************************************************************************/
;/*                                                                          */
;/* MODULE : SAVETIME                                                        */
;/*                                                                          */
;/* This module defines SAVETIME, a routine to read and store timing info    */
;/* from Counter 0 of the PC. It can be used to do performance measurements  */
;/* but note that timings are stored in units of clock ticks (.84 microsecs) */
;/*                                                                          */
;/*                                                                          */
;/****************************************************************************/

;.model medium, pascal

;/****************************************************************************/
;/* Set up the constants used in the SAVETIME.                               */
;/****************************************************************************/

Timer_0       equ        40h                 ; 8253 counter 0 port
Timer_Ctl     equ        43h                 ; 8253 control port
Timer_Set     equ        00110100b           ; 8253 counter 0, set LOB/HOB
Timer_0_Latch equ        00h                 ; 8253 command to save count


;/****************************************************************************/
;/* The following defines the static data used by the timer routine.         */
;/****************************************************************************/

.386

;_DATA16         segment use16 word public 'DATA'
;_DATA16         segment word use16 public 'NEWDATA'
_DATA16IOPL     segment word use16 public 'DATA'

FirstCall     dw         1                   ; TRUE => first call of dll

_DATA16IOPL     ends



;/****************************************************************************/
;/* The following define the routine to save the timer info in the array. It */
;/* checks if this is the first call and if so, it initializes Counter 0 to  */
;/* count in mode 2 instead of mode 3.                                       */
;/****************************************************************************/

;              .code

;_CODE16         segment word use16 public 'NEWCODE'
_CODE16IOPL     segment word use16 public 'CODE'

              assume CS:_CODE16IOPL

public          SAVETIME

;SAVETIME      proc far uses ds di si
SAVETIME      proc far

              push      ds
              push      di
              push      si


;/****************************************************************************/
;/* If this is the first call of the routine then set the counter to mode 0  */
;/****************************************************************************/

              mov     ax, seg _DATA16IOPL
              mov     ds, ax                 ; Set up DS to this data segment

              assume  DS:_DATA16IOPL

              cmp     FirstCall, 0
              jz      short MainBody         ; Skip initialization

              mov     FirstCall, 0           ; Set initialization flag to FALSE

              mov     al, Timer_Set
              out     Timer_Ctl, al          ; Set counter 0 parameters, prime
                                             ; Load trigger
              xor     al, al                 ; 0 will give full count of 65536
              jmp $+2                        ; Ensure 5 clocks for 8253 recover
              out     Timer_0, al            ; Load low order byte
              jmp $+2                        ; 8253 recovery time
              out     Timer_0, al            ; Load high order byte
              mov     cx, -1                 ; Must be sure previous countdown
DummyLoop:    loop    DummyLoop              ; has completed, so spin for a
                                             ; while to guarantee it

MainBody:

;/****************************************************************************/
;/* Read the counter information and return it                               */
;/****************************************************************************/

              mov    al, Timer_0_Latch       ; Timer 0, latch
              out    Timer_Ctl, al           ; Latch current count in 8253
              jmp    $+2                     ; Ensure 5 clocks for 8253 recover
              in     al, Timer_0             ; Read in low order byte
              mov    ah, al                  ; Tuck it out of the way
              jmp    $+2                     ; Ensure 5 clocks for 8253 recover
              in     al, Timer_0             ; Read in high order byte
              sti                            ; Restore interrupts again
              xchg   ah, al                  ; Get in right order in register
              neg    ax                      ; Get up count from down

Quit:         pop       si
              pop       di
              pop       ds

              ret

SAVETIME      endp

_CODE16IOPL   ends

              end

;/* SAVETIME.asm */
