📄 cpu586.asm
字号:
call F000_Out_8042_Pin
in al,PORT61 ;save PORT61 value
IODELAY
push ax
call far ptr S_CPU
pop ax ;restore PORT61 value
out PORT61,al
IODELAY
;--------------------------------------------------------------
;compare results of KB high & KB low speed, take the higher one
;--------------------------------------------------------------
;restore KB high speed results in ax, di
mov al,bh
mul dl
cmp ax,si
pop ax
pop di
jae AUTO_CPUS_READY
;use KB high speed result
mov bx,ax
mov dx,di
AUTO_CPUS_READY:
endif; TOGGLE_8042_FOR_CPU_CLK_DETECT
;write CPU_INTERNAL_CLOCK[bp] with tested value
mov al,bh ;system clock(integer) in AL
mul dl ;Sing/doub/treb value in DL
mov CPU_INT_CLOCK[bp],ax ;actual internal CPU clock
mov dl,FIXED_DISK_STEP[bp] ;get CPU type
and dl,CPU_TYPE_MASK ;get CPU type
;;;;; ;special table for P24T , because the clock mode is x2.5
;;;;; cmp dl,TYPE_P24T
;;;;; jne Not_P24T_2Point5
;;;;; test byte ptr OVERRIDE[bp],DOUBLE_CLOCK
;;;;; jz Not_P24T_2Point5
;;;;; mov si,offset P24T_Int_Clock_Tbl
;;;;; jmp R_Off_Clk
;;;;; Not_P24T_2Point5:
;special table for P5 & M1 & K5
mov bh,byte ptr FIXED_DISK_STEP[bp]
and bh,CPU_TYPE_MASK
mov si,offset CPU_Int_Clock_Tbl ;table for PENTIUM
cmp bh,TYPE_586 ;Pentium CPU?
je Round_Off_It
cmp bh,TYPE_AMD5K86 ;K5 CPU?
je Round_Off_It
mov si,offset M1_Int_Clock_Tbl ;table for M1
cmp bh,TYPE_M1 ;M1 CPU?
je Round_Off_It
jmp Not_Pentium
Round_Off_It:
mov al,dh
R_Off_Clk:
;far call Round_Off_Clock
FAR_CALL <offset Round_Off_Clock>,0E000h
ifndef CPU_Support_Above_GXM
mov CPU_INT_CLOCK[bp],bl ;actual internal CPU clock
push G_RAM
pop es
mov bl,cs:[si+2] ;SI+2 = system clock
endif ;CPU_Support_Above_GXM
call Get_IDT_WinChip_Clock ;For IDT WinChip
;change Ratio
cmp byte ptr CPU_BRAND[bp], CPU_BRAND_CYRIX
jne NotM1_Cpu
call Check_M2Cpu
je NotM1_Cpu
;There is two combination for 150Mhz , 75*2 and 50*3 , the default is 75*2
;, we need to check the clock mode , if 3x , change host clock to 50Mhz
mov al,byte ptr FIXED_DISK_STEP[bp]
and al,CPU_TYPE_MASK
cmp al,TYPE_M1 ;M1 CPU?
jne NotM1_Cpu
cmp byte ptr CPU_INT_CLOCK[bp],150 ;150Mhze ?
jne NotM1_Cpu
;Now , BIOS set 150Mhz as 60x2.5 for M2
mov al,0FEh ;DIR0 of M2 CPU
out 22h,al
in al,23h
and al,0f7h ;mask bit 3
cmp al,52H ;x2.5 ?
je NotM1_Cpu ;yes
cmp al,51h ;x2 ?
jne Not_M2X2
mov bl,CPU75 ;set host clock 75x2
Not_M2X2:
test byte ptr OVERRIDE[bp],THREE_CLOCK ;3x mode ?
jz NotM1_Cpu
;set 50Mhz host clock if 3x mode
mov bl,CPU50 ;set host clock
NotM1_Cpu:
ifdef K586_68MHz_Show_133MHz
cmp al,TYPE_AMD5K86
jne Not_AMD5K86
cmp byte ptr CPU_INT_CLOCK[bp],120 ;150Mhz ?
jne Not_AMD5K86
;Set 166MHz For AMD5K86 Use 68MHz
mov byte ptr CPU_INT_CLOCK[bp],117 ;166Mhz
mov bl,CPU66 ;66x1.75
Not_AMD5K86:
endif; K586_68MHz_Show_133MHz
mov byte ptr es:[CPU_CLOCK],bl
Not_P54C:
Not_Pentium:
;Show 100Mhz if 99Mhz
cmp byte ptr CPU_INT_CLOCK[bp],132
je Set_133
cmp byte ptr CPU_INT_CLOCK[bp],99
jne @F
Set_133:
inc byte ptr CPU_INT_CLOCK[bp]
@@:
ifdef TOGGLE_8042_FOR_CPU_CLK_DETECT
mov al,1
call F000_Out_8042_Pin
endif; TOGGLE_8042_FOR_CPU_CLK_DETECT
;-------------------
;Clear temporary RAM
;-------------------
mov ax,G_RAM
mov es,ax
assume es:G_RAM
;----------------------------
;Special treatment for TI CPU
;----------------------------
mov byte ptr es:CPU_CLOCK,bl
CpuSpeedEnd:
clc
ret
Measure_CPU_Speed endp
;Input : BX - real CPU clock (detected by RDTSC instruction)
;Output: carry set - It is AMD K6 model 8 CPU &
; CPU_INT_CLOCK[bp] & G_RAM:[CPU_CLOCK] are filled
; no carry - Not K6 model 8 CPU
Get_AMD_Model8_Clock_Tbl Proc Near
push ax
push bx
extrn Check_K6_CPU:near
call Check_K6_CPU
clc
jne Not_Model8_CPU
call Read_CpuID ;read CPU ID
cmp ax,0588h
jb Not_Model8_CPU ;No, skip !
mov ecx,0c0000087h ;read bus ratio steping
RDMSR
and ax, 00000111b ;AL = 000 -> 4.5x
; 001 -> 5.0x
; 010 -> 4.0x
; 011 -> 5.5x
; 100 -> 2.5x
; 101 -> 3.0x
; 110 -> 6.0x
; 111 -> 3.5x
mov si,ax
add si,offset K6_ClkRatio
CalcHostClk label near
; Note : The following instruction cause Cyrix M2 hang up.
; movzx cx,byte ptr cs:[si] ;get clock ratio
; mov ax,bx
; shl ax,1 ;multipler by 2
; idiv cx ;get host clock in AL
movzx cx,byte ptr cs:[si] ;get clock ratio
shl bx, 1 ;multipler by 2
xor ax, ax
DivLoop:
sub bx, cx
jc short DivideOk
inc ax
jmp short DivLoop
DivideOk:
;now AL contains raw host clock
;look for formal host clock
mov di,offset K6_HostClk
NextHostClk:
cmp byte ptr cs:[di+HOSTCLK_SIZE],0 ;end of host clock table ?
je HostClkExit ;yes
cmp al,cs:[di] ;match ?
jae HostClkExit
add di,HOSTCLK_SIZE ;point to next entry
jmp NextHostClk
HostClkExit:
;Calculate CPU real clock by multipling host clock by clock ratio
mov ax,cs:[di+3] ;get factor to calculate clock
movzx cx,byte ptr cs:[si] ;get clock ration in /2
mul cx
shr ax,1
add ax,5 ;for round off
mov cx,10
idiv cx
call ChkIf_X99Mhz ;Add 1 if x99Mhz
push G_RAM
pop es
mov CPU_INT_CLOCK[bp],ax ;actual internal CPU clock
mov cl,cs:[di+2] ;get formal host clock
mov byte ptr es:[CPU_CLOCK],cl
;R04 - starts
;Record Host clock of P5 in shadow memory for future usage
extrn P6HostClock:near
pushad
push ds
F000_call F000_Shadow_W ;F-segment shadow R/W
mov ax, DGROUP ;DS=F000
mov ds, ax
mov si, offset DGROUP:P6HostClock
mov al, cs:[di+1] ;get host clock frequency
mov [si], al ;save clock value in shadow
F000_call F000_Shadow_R ;F-segment shadow Readonly
pop ds
popad
;R04 - ends
Get_Model8_Clock_Tbl_OK:
stc
pop bx
pop ax
ret
Not_Model8_CPU:
clc
pop bx
pop ax
ret
Get_AMD_Model8_Clock_Tbl Endp
;Input : BX - real CPU clock (detected by RDTSC instruction)
;Output: carry set - It is Cyrix M2 CPU &
; CPU_INT_CLOCK[bp] & G_RAM:[CPU_CLOCK] are filled
; no carry - Not Cyrix M2 CPU
Get_M2_Clock_Tbl proc near
push ax
push bx
cmp byte ptr CPU_BRAND[bp], CPU_BRAND_CYRIX
clc
jne Not_M2_CPU
mov al, 0FEh
out 22h, al
in al, 23h
mov ah, al
and ah, 11110000b ;mask bits[7:4]
cmp ah, 50h ; Is M2 CPU present ?
clc
jne Not_M2_CPU
xor ah,ah
and al,00000111b ;AL = 51h or 59h x2
; 52h or 5Ah x2.5
; 53h or 5Bh x3
; 54h or 5Ch x3.5
; 55h or 5DH x4
dec ax
mov si,ax
add si,offset M2_ClkRatio
jmp CalcHostClk
Not_M2_CPU:
pop bx
pop ax
ret
Get_M2_Clock_Tbl ENDP
M2_ClkRatio db 4 ;x2 ,000
db 5 ;x2.5 ,001
db 6 ;x3 ;010
db 7 ;x3.5 ;011
db 8 ;x4 ;100
K6_ClkRatio db 9 ;x4.5 ,000
db 10 ;x5 ,001
db 8 ;x4 ;010
db 11 ;x5.5 ;011
db 5 ;x2.5 ;100
db 6 ;x3.0 ;101
db 12 ;x6.0 ;110
db 7 ;x3.5 ;111
;possible host clock table for P6 class CPU
K6_HostClk:
db 148,150,CPU100 ;150Mhz
dw 1500 ;for real CPU frequency calculation
HOSTCLK_SIZE EQU ($ - offset K6_HostClk)
db 139,140,CPU100 ;140Mhz
dw 1400 ;for real CPU frequency calculation
db 134,135,CPU100 ;135Mhz
dw 1350 ;for real CPU frequency calculation
db 132,133,CPU100 ;133Mhz
dw 1333 ;for real CPU frequency calculation ;R03
db 129,130,CPU100 ;130Mhz
dw 1300 ;for real CPU frequency calculation
db 123,125,CPU100 ;125Mhz
dw 1250 ;for real CPU frequency calculation
db 118,120,CPU100 ;120Mhz
dw 1200 ;for real CPU frequency calculation
db 113,115,CPU100 ;115Mhz
dw 1150 ;for real CPU frequency calculation
;R03 - start
db 111,112,CPU100 ;112Mhz
dw 1120 ;for real CPU frequency calculation
;R03 - end
db 108,110,CPU100 ;110Mhz
dw 1100
db 103,105,CPU100 ;105Mhz
dw 1050
db 96,100,CPU100 ;100Mhz
dw 1000 ;for real CPU frequency calculation
db 92,95,CPU95 ;95Mhz
dw 950
db 88,90,CPU90 ;90Mhz
dw 900
db 80,83,CPU83 ;83Mhz
dw 832
db 71,75,CPU75 ;75Mhz
dw 750
ifndef K6_NO_68MHz
db 68,68,CPU66 ;68.5Mhz
dw 685
endif; K6_NO_68MHz
db 64,66,CPU66 ;66Mhz
dw 666
db 58,60,CPU60 ;60Mhz
dw 600
db 53,55,CPU60 ;55Mhz
dw 550
db 48,50,CPU50 ;50Mhz
dw 500
db 0 ;end of table
;Function : Increment by one if measured frequency is x99Mhz
;Input : ax - CPU frequency in Mhz
;Output : ax - modified CPU frequency
ChkIf_X99Mhz proc near
push bx
push ax ;save original frequency
mov bx,100
Sub100:
cmp ax,bx ;value below 100 ?
jbe Less100 ;yes
sub ax,bx ;no, subtract 100 until the value
jmp Sub100 ;below 100
Less100:
cmp al,99 ;x99Mhz ?
pop ax ;restore original value
jne Not_X99Mhz
inc ax ;increment by 1 if x99Mhz
Not_X99Mhz:
pop bx
ret
ChkIf_X99Mhz endp
Get_IDT_WinChip_Clock Proc Near
push eax
push ecx
call Check_IdtCpu ;is IDT C6 CPU ?
jne Not_IdtC6_WinChip
mov eax,1 ;eax = 1 to read CPU ID
db 0fh,0A2h ;CPU ID instruction
cmp al, 80h
jb Not_IdtC6_WinChip
call fPROC_If_WinChip2A
je WinChip2A_Or_WinChip3_Clock
cmp al, 90h
jb WinChip2_Clock
WinChip2A_Or_WinChip3_Clock:
call WinChip2A_Clock_Multiplier_In_AH
mov cl, ah
and cl, 03h
mov ch, ah
shr ch, 2
add cx, 0202h
mov ax, CPU_INT_CLOCK[bp] ;actual internal CPU clock
div ch
mul cl
jmp Locate_IdtC6_Host_Freq
WinChip2_Clock:
mov ecx,10ah
db 0fh,32h ;Ratio of processor
;al = 0 => 2x
;al = 1 => 3x
;al = 2 => 4x
;al = 3 => 5x
add al,2
mov cl,al
mov ax,word ptr CPU_INT_CLOCK[bp] ;actual internal CPU clock
div cl
Locate_IdtC6_Host_Freq:
mov si,offset IdtC6_Bus_Clock_Tbl_List
Next_IdtC6_WinChip_Clock:
mov bl,byte ptr cs:[si+1]
cmp al,byte ptr cs:[si]
jae Get_IdtC6_WinChip_Clock_OK
cmp byte ptr cs:[si+2],0
je Get_IdtC6_WinChip_Clock_OK
add si,2
jmp Next_IdtC6_WinChip_Clock
Get_IdtC6_WinChip_Clock_OK:
Not_IdtC6_WinChip:
pop ecx
pop eax
ret
Get_IDT_WinChip_Clock Endp
IdtC6_Bus_Clock_Tbl_List:
db 98,CPU100 ;100MHz
db 81,CPU83 ;100MHz
db 73,CPU75 ;100MHz
db 64,CPU66 ;100MHz
db 58,CPU60 ;100MHz
db 48,CPU50 ;100MHz
db 0
DIVID MACRO
mov ax,di
div bx
endm
PORT61 EQU 61H
PORT8254 EQU 42H
DATA8254 EQU 43H
COUNT EQU 3EH
;-----------------------------------------------------------------
;Input : None
;Output : BH : System Clock in interger
; BL : System Clock i.e. 10h = 16MHz
; 20h = 20MHz
; 30h = 25MHz
; 40h = 33MHz
; 50h = 40MHz
; 60h = 50MHz
; 60h = 60MHz
; 60h = 66MHz
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -