blob: 0194a62f98de6873d082435fa7e0fbf292a0d857 [file] [log] [blame]
;****************************************************************************
;*
;* SciTech Nucleus Graphics Architecture
;*
;* Copyright (C) 1991-1998 SciTech Software, Inc.
;* All rights reserved.
;*
;* ======================================================================
;* |REMOVAL OR MODIFICATION OF THIS HEADER IS STRICTLY PROHIBITED BY LAW|
;* | |
;* |This copyrighted computer code contains proprietary technology |
;* |owned by SciTech Software, Inc., located at 505 Wall Street, |
;* |Chico, CA 95928 USA (http://www.scitechsoft.com). |
;* | |
;* |The contents of this file are subject to the SciTech Nucleus |
;* |License; you may *not* use this file or related software except in |
;* |compliance with the License. You may obtain a copy of the License |
;* |at http://www.scitechsoft.com/nucleus-license.txt |
;* | |
;* |Software distributed under the License is distributed on an |
;* |"AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or |
;* |implied. See the License for the specific language governing |
;* |rights and limitations under the License. |
;* | |
;* |REMOVAL OR MODIFICATION OF THIS HEADER IS STRICTLY PROHIBITED BY LAW|
;* ======================================================================
;*
;* Language: 80386 Assembler, NASM or TASM
;* Environment: IBM PC 32 bit Protected Mode.
;*
;* Description: Assembly support functions for the Nucleus library for
;* the high resolution timing support functions provided by
;* the Intel Pentium and compatible processors.
;*
;****************************************************************************
IDEAL
include "scitech.mac" ; Memory model macros
header _gatimer
begcodeseg _gatimer
ifdef USE_NASM
%macro mCPU_ID 0
db 00Fh,0A2h
%endmacro
else
MACRO mCPU_ID
db 00Fh,0A2h
ENDM
endif
ifdef USE_NASM
%macro mRDTSC 0
db 00Fh,031h
%endmacro
else
MACRO mRDTSC
db 00Fh,031h
ENDM
endif
;----------------------------------------------------------------------------
; bool _GA_haveCPUID(void)
;----------------------------------------------------------------------------
; Determines if we have support for the CPUID instruction.
;----------------------------------------------------------------------------
cprocstart _GA_haveCPUID
enter_c
pushfd ; Get original EFLAGS
pop eax
mov ecx, eax
xor eax, 200000h ; Flip ID bit in EFLAGS
push eax ; Save new EFLAGS value on stack
popfd ; Replace current EFLAGS value
pushfd ; Get new EFLAGS
pop eax ; Store new EFLAGS in EAX
xor eax, ecx ; Can not toggle ID bit,
jnz @@1 ; Processor=80486
mov eax,0 ; We dont have CPUID support
jmp @@Done
@@1: mov eax,1 ; We have CPUID support
@@Done: leave_c
ret
cprocend
;----------------------------------------------------------------------------
; uint _GA_getCPUIDFeatures(void)
;----------------------------------------------------------------------------
; Determines the CPU type using the CPUID instruction.
;----------------------------------------------------------------------------
cprocstart _GA_getCPUIDFeatures
enter_c
xor eax, eax ; Set up for CPUID instruction
mCPU_ID ; Get and save vendor ID
cmp eax, 1 ; Make sure 1 is valid input for CPUID
jl @@Fail ; We dont have the CPUID instruction
xor eax, eax
inc eax
mCPU_ID ; Get family/model/stepping/features
mov eax, edx
@@Done: leave_c
ret
@@Fail: xor eax,eax
jmp @@Done
cprocend
;----------------------------------------------------------------------------
; void _GA_readTimeStamp(GA_largeInteger *time)
;----------------------------------------------------------------------------
; Reads the time stamp counter and returns the 64-bit result.
;----------------------------------------------------------------------------
cprocstart _GA_readTimeStamp
mRDTSC
mov ecx,[esp+4] ; Access directly without stack frame
mov [ecx],eax
mov [ecx+4],edx
ret
cprocend
;----------------------------------------------------------------------------
; N_uint32 GA_TimerDifference(GA_largeInteger *a,GA_largeInteger *b)
;----------------------------------------------------------------------------
; Computes the difference between two 64-bit numbers (a-b)
;----------------------------------------------------------------------------
cprocstart GA_TimerDifference
ARG a:DPTR, b:DPTR, t:DPTR
enter_c
mov ecx,[a]
mov eax,[ecx] ; EAX := b.low
mov ecx,[b]
sub eax,[ecx]
mov edx,eax ; EDX := low difference
mov ecx,[a]
mov eax,[ecx+4] ; ECX := b.high
mov ecx,[b]
sbb eax,[ecx+4] ; EAX := high difference
mov eax,edx ; Return low part
leave_c
ret
cprocend
; Macro to delay briefly to ensure that enough time has elapsed between
; successive I/O accesses so that the device being accessed can respond
; to both accesses even on a very fast PC.
ifdef USE_NASM
%macro DELAY_TIMER 0
jmp short $+2
jmp short $+2
jmp short $+2
%endmacro
else
macro DELAY_TIMER
jmp short $+2
jmp short $+2
jmp short $+2
endm
endif
;----------------------------------------------------------------------------
; void _OS_delay8253(N_uint32 microSeconds);
;----------------------------------------------------------------------------
; Delays for the specified number of microseconds, by directly programming
; the 8253 timer chips.
;----------------------------------------------------------------------------
cprocstart _OS_delay8253
ARG microSec:UINT
enter_c
; Start timer 2 counting
mov _ax,[microSec] ; EAX := count in microseconds
mov ecx,1196
mul ecx
mov ecx,1000
div ecx
mov ecx,eax ; ECX := count in timer ticks
in al,61h
or al,1
out 61h,al
; Set the timer 2 count to 0 again to start the timing interval.
mov al,10110100b ; set up to load initial (timer 2)
out 43h,al ; timer count
DELAY_TIMER
sub al,al
out 42h,al ; load count lsb
DELAY_TIMER
out 42h,al ; load count msb
xor di,di ; Allow max 64K loop iterations
@@LoopStart:
dec di ; This is a guard against the possibility that
jz @@LoopEnd ; someone eg. stopped the timer behind our back.
; After 64K iterations we bail out no matter what
; (and hope it wasn't too soon)
mov al,00000000b ; latch timer 0
out 43h,al
DELAY_TIMER
in al,42h ; least significant byte
DELAY_TIMER
mov ah,al
in al,42h ; most significant byte
xchg ah,al
neg ax ; Convert from countdown remaining
; to elapsed count
cmp ax,cx ; Has delay expired?
jb @@LoopStart ; No, so loop till done
; Stop timer 2 from counting
@@LoopEnd:
in al,61H
and al,0FEh
out 61H,al
; Some programs have a problem if we change the control port; better change it
; to something they expect (mode 3 - square wave generator)...
mov al,0B6h
out 43h,al
leave_c
ret
cprocend
endcodeseg _gatimer
END