aboutsummaryrefslogtreecommitdiff
path: root/board/MAI/bios_emulator/scitech/src/common/_gatimer.asm
blob: 0194a62f98de6873d082435fa7e0fbf292a0d857 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
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