diff options
Diffstat (limited to 'board/MAI/bios_emulator/scitech/src/common/_gatimer.asm')
-rw-r--r-- | board/MAI/bios_emulator/scitech/src/common/_gatimer.asm | 248 |
1 files changed, 248 insertions, 0 deletions
diff --git a/board/MAI/bios_emulator/scitech/src/common/_gatimer.asm b/board/MAI/bios_emulator/scitech/src/common/_gatimer.asm new file mode 100644 index 0000000..0194a62 --- /dev/null +++ b/board/MAI/bios_emulator/scitech/src/common/_gatimer.asm @@ -0,0 +1,248 @@ +;**************************************************************************** +;* +;* 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 + |