📄 detect.asm
字号:
;
; Copyright (C) 1996-2002 Supernar Systems, Ltd. All rights reserved.
;
; Redistribution and use in source and binary forms, with or without
; modification, are permitted provided that the following conditions are
; met:
;
; 1. Redistributions of source code must retain the above copyright
; notice, this list of conditions and the following disclaimer.
;
; 2. Redistributions in binary form must reproduce the above copyright
; notice, this list of conditions and the following disclaimer in the
; documentation and/or other materials provided with the distribution.
;
; 3. The end-user documentation included with the redistribution, if any,
; must include the following acknowledgment:
;
; "This product uses DOS/32 Advanced DOS Extender technology."
;
; Alternately, this acknowledgment may appear in the software itself, if
; and wherever such third-party acknowledgments normally appear.
;
; 4. Products derived from this software may not be called "DOS/32A" or
; "DOS/32 Advanced".
;
; THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS" AND ANY EXPRESSED
; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
; DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
; OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
; ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
;
;
;=============================================================================
; Get Protected Mode Info
;=========================
; In: Nothing
; Out: AX = return code:
; 0000h = DOS version below 4.00
; 0001h = no 80386+ detected
; 0002h = system already in protected mode and no VCPI or DPMI found
; 0003h = DPMI - host is not 32bit
; 0004h = VCPI - incompatible PIC mappings
; CF = set on error, if no error:
; BX = number of paragraphs needed for protected mode data (may be 0)
; CL = processor type
; CH = protected mode type:
; 00h = raw
; 01h = XMS
; 02h = VCPI
; 03h = DPMI
; DX = size of removable Kernel body (in bytes)
; DI = base of removable Kernel body
;=============================================================================
Align 4
@area1_db label byte
@area1_dw label word
@area1_dd label dword
pm32_info:
cld
push ds es ; preserve registers
push cs cs ; DS = CS (_KERNEL)
pop ds es
If EXEC_TYPE eq 2
call show_debug_string ; show debug string
EndIf
mov ah,30h ; get DOS version
int 21h
cmp al,4 ; if DOS version is below 4.00
mov ax,0 ; return with error code 0
jb @@fail
call cpu_detect ; get processor type
mov cputype,al ; store processor type
cmp al,3 ; check if processor is 80386+
mov ax,1 ; error in case no 80386+
jae @@0
jmp @@fail
@@0: call fpu_detect ; detect/initialize FPU
mov fputype,al
mov ax,4300h ; check for XMS
int 2Fh
cmp al,80h
jnz @@1 ; jump if XMS not found
push es
mov ax,4310h
int 2Fh
mov xms_call[0],bx ; store XMS driver address
mov xms_call[2],es
mov ah,30h
int 21h ; HIMEM.SYS bug fix
mov ah,88h
xor bx,bx
call dword ptr xms_call ; get XMS v3.0 free mem in KB
test bl,bl ; if no XMS v3.0, use v2.0
jz @@0001
mov ah,08h
call dword ptr xms_call ; get XMS v2.0 free mem in KB
movzx eax,ax
@@0001: mov xms_data,eax
pop es
@@1: test pm32_mode,00000001b ; check order of DPMI/VCPI detection
jz @@2
call @@detect_VCPI ; check for VCPI first
call @@detect_DPMI ; check for DPMI second
jmp @@3 ; neither found, go on to raw check
@@2: call @@detect_DPMI ; check for DPMI first
call @@detect_VCPI ; check for VCPI second
@@3: smsw ax ; AX = machine status word
and al,1 ; is system in protected mode?
mov ax,2 ; error code in case in protected mode
jnz @@fail ; if in protected mode, fail
cmp xms_data,0 ; check if XMS_mem is present
setnz ch ; if yes, pmode type is XMS
mov bx,80h ; BX = memory requirement (IDT)
@@4: movzx ax,pm32_rmstacks ; size of real mode stack area
imul ax,pm32_rmstacklen
add bx,ax
movzx ax,pm32_pmstacks ; size of protected mode stack area
imul ax,pm32_pmstacklen
add bx,ax
movzx ax,pm32_callbacks ; size of callbacks
imul ax,25
add ax,0Fh
shr ax,4
add bx,ax
mov ax,pm32_selectors ; size of GDT
add ax,SYSSELECTORS+1
shr ax,1
add bx,ax
@@done: xor ax,ax ; success code, also clear carry flag
mov cl,cputype
mov pmodetype,ch ; store pmode type
mov dx,offs @kernel_end - offs @kernel_beg
mov di,offs @kernel_beg
@@exit: pop es ds ; restore other registers
retf ; return
@@fail: stc ; carry set, failed
jmp @@exit
;=============================================================================
@@detect_DPMI: ; detect a DPMI host
pop bp
mov ax,1687h ; check for DPMI
int 2Fh
test ax,ax ; DPMI present?
jnz @@d0 ; if no, exit routine
mov ax,1 ; error code in case no processor 386+
cmp cl,3 ; is processor 386+? (redundant)
jb @@fail ; if no, fail
mov al,3 ; error code in case DPMI not 32bit
test bl,1 ; is DPMI 32bit?
jz @@fail ; if no, fail
mov word ptr dpmiepmode[0],di ; store DPMI initial mode switch addx
mov word ptr dpmiepmode[2],es
mov bx,si ; BX = number of paragraphs needed
mov ch,3 ; pmode type is 3 (DPMI)
jmp @@done ; go to done ok
@@d0: jmp bp ; return to calling routine
;=============================================================================
@@detect_VCPI: ; detect a VCPI server
pop bp
xor ax,ax ; get INT 67h vector
mov es,ax
mov ax,es:[67h*4]
or ax,es:[67h*4+2] ; is vector NULL
jz @@d0 ; if yes, no VCPI
mov ax,0DE00h ; call VCPI installation check
int 67h
test ah,ah ; AH returned as 0?
jnz @@d0 ; if no, no VCPI
mov ax,0DE0Ah ; get PIC mappings
int 67h
mov picmaster,bl
mov picslave,cl
mov ax,0004h ; error code 4 in case of exit
cmp bl,cl ; BL=CL, only one PIC available
je @@fail
cmp bl,30h ; PICs mapped on system vectors?
je @@fail
cmp cl,30h
je @@fail
test bl,bl ; should not be mapped on INT 00h
je @@fail
test cl,cl
je @@fail
mov edx,xms_data ; EDX=get free XMS memory
mov ecx,edx ; ECX=free XMS memory in KB
jecxz @@v1 ; skip if none
test pm32_mode,00001000b ; check if VCPI+XMS alloc scheme
jz @@vA ; if not, jump (save some DOS memory)
call xms_allocmem ; alloc XMS memory in EDX
mov di,dx ; DI=handle
dec ax ; if AX=0001, no error occured
jz @@v1
@@vA: xor ecx,ecx ; if error, XMS memory in ECX = 0
@@v1: mov ax,0DE03h
int 67h ; EDX=free VCPI pages
push es ecx edx di
test pm32_mode,00000100b ; check if VCPI smart pagetable alloc
jz @@v1a ; no, use standard detection
mov ah,48h ; allocate 4K block of memory
mov bx,0100h ; for VCPI pagetable
int 21h
jc @@v1a ; INT 21h failed, use standard alloc
mov es,ax ; ES=returned segment
xor di,di ; DI=zero pointer
sub sp,8*3 ; DS:SI=pointer to structure
mov si,sp
push ds
push ss
pop ds
mov ax,0DE01h ; get PM interface
int 67h
pop ds
add sp,8*3 ; discard structure on stack
mov ah,49h ; discard pagetable and free DOS mem
int 21h
mov eax,1000h ; pagetable limit 4K
sub ax,di ; minus used part
shr ax,2 ; convert to 4K pages
jmp @@v1b
@@v1a: xor eax,eax
@@v1b: pop di edx ecx es
mov esi,ecx ; ECX=XMS free mem,EDX=VCPI free pages
shr esi,2 ; ESI=XMS_freemem/4 (to match 4Kpages)
lea esi,[edx+esi+3FFh] ; ESI=XMS_4Kmem+VCPI_4Kpages+4M_align
sub esi,eax ; minus free 0th pagetable space
jnc @@v1c ; just in case...
adc esi,eax
@@v1c: shr esi,10 ; ESI=ESI/1024
jecxz @@v2
mov dx,di
mov ah,0Ah ; free what was allocated
call dword ptr xms_call
@@v2: movzx ax,pm32_maxpages
cmp ax,si
jbe @@v3
mov ax,si
@@v3: test ax,ax ; now if no pages, check for
jnz @@v5 ; DOS/32A, and if present, use its
pushad ; pages and pagetables
mov bp,sp
mov ax,0FF88h ; check if running under DOS/32A
int 21h
cmp eax,'ID32'
jnz @@v4
mov [bp+1Ch],si ; if yes, store pagetables in AX
@@v4: popad
@@v5: cmp al,64 ; limit the number of pagetables to
jbe @@v6 ; maximum 64, = 256MB
mov al,64
@@v6: mov pagetables,al ; BX = VCPI page tables needed
add al,pm32_maxfpages ; + physical memory mappable pages
shl ax,8 ; 100h paragraphs per page table
add ax,100h+100h+0FFh+7+80h ; +page_dir+0th_page+align_buf+TSS+IDT
mov bx,ax
mov ch,2 ; pmode type is 2 (VCPI)
jmp @@4 ; go to figure other memory needed
@@v0: jmp bp ; return to calling routine
;=============================================================================
cpu_detect: ; detect: 286, 386, 486, 586 etc
cli
mov cl,2 ; CL: cputype=2 (80286)
pushf
pop ax
or ax,0F000h
push ax
popf
pushf
pop ax
and ax,0F000h
jne @@l2
jmp @@x1
@@l2: inc cl ; CPU = 80386
pushfd
pop eax
mov edx,eax
xor eax,00040000h
push eax
popfd
pushfd
pop eax
xor eax,edx
jne @@l3
jmp @@x1
@@l3: inc cl ; CPU = 80486
push edx
popfd
pushfd
pushfd
pop eax
mov edx,eax
xor eax,00200000h
push eax
popfd
pushfd
pop eax
xor eax,edx
jne @@l4
jmp @@x2
@@l4: mov eax,1
db 0Fh, 0A2h ; CPUID
and ah,0Fh
mov cl,ah
@@x2: popfd
xor eax,eax
xor edx,edx
@@x1: mov al,cl
sti
ret
fpu_detect: ; detect 8087, 287, 387, 487 etc
push large 0
mov bp,sp
fninit
fnstcw word ptr [bp+2]
mov ax,word ptr [bp+2]
cmp ah,03h
jnz @@done ; done: no FPU present
mov word ptr [bp],1
and word ptr [bp+2],0FF7Fh
wait
fldcw word ptr [bp+2]
fdisi
fstcw word ptr [bp+2]
wait
test word ptr [bp+2],0080h
jnz @@done ; done: 8087 is present
mov word ptr [bp],2
fninit
wait
fld1
wait
fldz
wait
fdivp st(1),st
wait
fld st(0)
wait
fchs
wait
fcompp
wait
fnstsw ax
wait
fnclex
wait
sahf
jz @@done ; done: 80287 is present
mov word ptr [bp],3
mov al,cputype
cmp al,4
jb @@done ; done: 80387 is present
mov byte ptr [bp],al ; done: 80487+ (build-in)
@@done: pop eax
and eax,7
jz @@exit
mov cx,8
@@loop: fldz ; set ST(0) to ST(7) to +ZERO
loop @@loop
finit ; reinitialize FPU
@@exit: ret
Align 4
@area1_end label byte
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -