;**************************************************************************** ;* ;* 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