📄 gxmcpuid.asm
字号:
;**************************************************************************
;*
;* CPUCPUID.ASM
;*
;* Copyright (c) 1999 National Semiconductor Corporation.
;* All Rights Reserved.
;*
;* Function:
;* CPU ID routines.
;*
;* $Revision:: 1 $
;*
;**************************************************************************
;;.MODEL TINY
.486P
INCLUDE MACROS.INC ; Macros
INCLUDE DEF.INC ; Definitions
INCLUDE PORT80.INC
_TEXT SEGMENT PUBLIC use16 'CODE'
EXTERN Delay_100_mSec:NEAR
EXTERN CpuRegWrite:NEAR
EXTERN CpuRegRead:NEAR
;**************************************************************************
;*
;* CPUTest
;*
;* Test CPU ID instruction
;*
;* Entry:
;* BX = return address
;*
;* Exit:
;*
;* Destroys:
;* EAX, EBX, ECX, EDX, (PORT80 destroys AL)
;*
;**************************************************************************
cpuTest PROC
mov gs, bx
; Normally, you would check to see if you can toggle bit 21
; in EFLAGS. If you can, GxmID is supported. If you can't, it isn't
; We are going to assume that GxmID is supported.
;
PORT80 POST_CPU_ID
; MAPEN MUST ALREADY BE ENABLED
; Enable the GxmID Instruction to be processed
mov al, CPU_CCR4
out CPU_INDEX, al
in al, CPU_DATA ; Read CCR4 register
or al, 80h ; Turn on GxmID
out CPU_DATA, al ; Write new modified version back
;
; Check GxmID with EAX = 0000 0000h
;
xor eax, eax ; Make sure EAX is clear
xor dx, dx ; Make sure DX is clear
xor cx, cx ; Make sure CX is clear
DB 00Fh, 0A2h ; Issue GxmID opcode
;
; 1st try "CyrixInstead"
;
cmp ebx, 69727943h ; ASCII for "Cyri"
jne cpuNSC ; try NSC
cmp ecx, 64616574h ; ASCII for "tead"
jne cpuNSC ; try NSC
cmp edx, 736E4978h ; ASCII for "xIns"
je IDGood
;
; check for newer CPU which have ID of "Geode by NSC"
;
cpuNSC:
cmp ebx, 'doeG' ; ASCII for "Geod"
jne cpuFail
cmp ecx, 'CSN ' ; ASCII for " NSC"
jne cpuFail
cmp edx, 'yb e' ; ASCII for "e by"
jne cpuFail
IDGood:
;
; Check GxmID with EAX = 0000 0001h
;
mov eax, 00000001h ; Function 1
DB 00Fh, 0A2h ; GxmID opcode
mov ecx, eax
PORT80 POST_CPU_STEPPING ; post_28h
cmp ecx, CPU_ID ; Stepping ID correct?
Jne cpuFail
PORT80 POST_CPU_FLAGS ; post_2ah
cmp edx, CPU_MXI ; Standard feature flags
jne cpuFail
jmp cpuDone ; Gxm Passed GxmID Check
cpuFail:
PORT80 POST_CPU_ID_FAIL ; post_2fh
hlt
cpuDone:
PORT80 POST_CPU_ID_GOOD ; post_2eh
mov bx, gs
jmp bx
cpuTest ENDP
;**************************************************************************
;*
;* CPU_Revision
;* Description: Pentium and newer CPU's support the CPU
;* ID instruction (0FA2H). This instruction uses the contents
;* of EAX to determine which subfunction to execute. The
;* standard subfunctions are:
;*
;* EAX = 0: Return Manufacturer Information
;* EAX = 1: Return Processor Stepping/Model Information
;*
;* The CPU ID instruction can be executed at any time. To
;* determine if a CPU supports CPU ID, the code checks to
;* see if bit 21 of the EFLAGS register is changeable.
;*
;* All current processors except Cyrix 6x86 power on with
;* CPU ID instruction enabled. In the Cyrix 6x86, the CPU ID
;* instruction must be enabled before it can be used.
;*
;* Each manufacturer supplies an application note that
;* describes the return values, which typically come
;* back in EAX, EBX, ECX and EDX. These application notes
;* are listed here:
;*
;* Entry:
;* Exit:
;* Destroys:
;*
;**************************************************************************
CPU_Revision PROC near public
pushfd ; Push EFLAGS
pop eax ; Store EFLAGS In EAX
mov ebx, eax ; Save Copy Of EFLAGS For Testing Later
xor eax, 0200000H ; Flip Bit 21
push eax ; Copy "Modified" EFLAGS To Stack
popfd ; Save "Modified" EAX To EFLAGS
pushfd ; Push "Modified" EFLAGS Back Onto Stack
pop eax ; Get EFLAGS Back Into EAX
cmp eax, ebx ; Did Bit 21 Change ??
mov eax, NOT SUCCESS ; Assume CPU ID Is supported
je NotSupported ; Nope, CPU ID Instruction Not Supported
mov eax, 1
CPU_ID_OPCODE
;
; In CPU ID Function #1, EAX Returns The Following:
;
; Bits 31:12 Reserved
; Bits 11:8 Instruction Family (4 = 486, 5 = Pentium, etc.)
; Bits 7:4 Model # (Vendor-defined model designator)
; Bits 3:0 Stepping # (Vendor-defined stepping number)
;
and eax, 0F00H ; Check Instruction Family and Model ID
shr eax, 8 ; Move Major Revision Into Low Byte
NotSupported:
ret
CPU_Revision ENDP
;**************************************************************************
;*
;* CPU_ID_SUPPORT
;*
;* Check To See If CPU Supports CPU ID Instruction
;*
;* (In All CPU's, Bit 21 In EFLAGS Is Changeable If
;* And Only If CPU ID Instruction Is Supported)
;*
;* Entry:
;* Exit:
;* Destroys
;*
;**************************************************************************
CPU_ID_Support PROC near public
pushfd ; Push EFLAGS
pop eax ; Store EFLAGS In EAX
mov ebx, eax ; Save Copy Of EFLAGS For Testing Later
xor eax, 0200000H ; Flip Bit 21
push eax ; Copy "Modified" EFLAGS To Stack
popfd ; Save "Modified" EAX To EFLAGS
pushfd ; Push "Modified" EFLAGS Back Onto Stack
pop eax ; Get EFLAGS Back Into EAX
cmp eax, ebx ; Did Bit 21 Change ??
mov eax, NOT SUCCESS ; Assume CPU ID Is supported
je NotSupported ; Nope, CPU ID Instruction Not Supported
xor eax, eax
CPU_ID_OPCODE
cmp ebx, Cyrix_EBX ; Check For Cyrix EBX
jne NotSupported
cmp ecx, Cyrix_ECX ; Check For Cyrix ECX
jne NotSupported
cmp edx, Cyrix_EDX ; Check For Cyrix EDX
jne NotSupported
mov eax, SUCCESS ; Return True (Non-Zero)
NotSupported:
ret
CPU_ID_Support ENDP
;**************************************************************************
;*
;* GetCPUSpeed
;*
;* Calculate CPU Speed Using RTSC (Read Time Stamp Counter)
;* Instruction.
;*
;* Entry:
;* Exit:
;* Destroys
;*
;**************************************************************************
GetCPUSpeed proc near public
DoItAgain:
pushf
cli
RDTSC_OPCODE
mov esi, edx
mov edi, eax
call Delay_100_mSec
RDTSC_OPCODE
popf
;
; The Following Is Impossible Unless The Counter
; Is Stuck
;
cmp eax, edi
je CounterBroke
cmp esi, edx
jne DoItAgain
;
; Calculate The Total Counts (Start - Final)
;
sub eax, edi
;
; Multiply By 10 The Old Fashioned Way
; To Get Counts/Second
;
mov ebx, eax
shl eax, 3
add eax, ebx
add eax, ebx
;//
;// Divide By A Million To Get MHz
;//
xor edx, edx
mov ebx, 1000000
div ebx
ret
CounterBroke:
Xor eax, eax
ret
GetCPUSpeed endp
;**************************************************************************
;*
;* GetPCISpeed
;*
;* Returns PCI Frequency,
;*
;* Entry:
;*
;* Exit: AX = pci speed in mhz
;*
;* Destroys: None
;*
;**************************************************************************
PCIFreqTable1:
db 4,6,4,6,7,8,7,5
PCIFreqTable2:
db 4,10,4,6,9,5,7,8
GetPCISpeed proc near public
push esi
push ebx
push ecx
push edx
push eax
;
; get Clk Multiplier
;
mov al, CPU_DIR0
out CPU_INDEX, al
in al, CPU_DATA
and al, 0Fh
mov dl, al
mov al, CPU_DIR1 ; get cpu revision
out CPU_INDEX, al
in al, CPU_DATA
lea si, PCIFreqTable1
cmp al, 50h ; which table to use
jb incsi2
lea si, PCIFreqTable2 ; walk Clock Multiplier Table
incsi2:
cmp dl, 0
je SavePCIFreq
inc si
dec dl
jmp incsi2
SavePCIFreq:
xor bx, bx
mov bl, byte ptr cs:[si]
push bx
call GetCPUSpeed ; returns cpu speed in AX
push ax
pop ax ; cpuspeed
pop bx ; PCI
xor dx, dx
div bx
PCIFreqDone:
mov dx, ax
pop eax
mov ax, dx
pop edx
pop ecx
pop ebx
pop esi
ret
GetPCISpeed endp
_TEXT ENDS
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -