560 lines
19 KiB
NASM
560 lines
19 KiB
NASM
;++
|
|
;
|
|
; Copyright (c) 1991 Microsoft Corporation
|
|
;
|
|
; Module Name:
|
|
;
|
|
; spdetect.asm
|
|
;
|
|
; Abstract:
|
|
;
|
|
; This modules detects a SystemPro or compatible. It is INCLUDED
|
|
; by SPIPI and other binaries whom need to know how to detect a
|
|
; SystemPro type MP machine (ie, setup). It must assemble more or
|
|
; less standalone and run in protect mode.
|
|
;
|
|
; Author:
|
|
;
|
|
; Ken Reneris (kenr) 13-Jan-1992
|
|
;
|
|
; Revision History:
|
|
;
|
|
;--
|
|
|
|
include halsp\i386\spmp.inc
|
|
include callconv.inc ; calling convention macros
|
|
|
|
|
|
_DATA SEGMENT DWORD PUBLIC 'DATA'
|
|
|
|
|
|
; spSystemType: SystemType is read from 0c80-0c83h.
|
|
; 0c80-0c81: 0e11: Compressed CPQ (5 bit encoding).
|
|
; 0c82: System Board type.
|
|
; 0c83: System Board revision level.
|
|
|
|
spSystemCpuTable dd 0e1101h ; CPQ01xx 386 ASP
|
|
dd 0e1111h ; CPQ11xx 486 ASP
|
|
dd 0e1150h ; CPQ50xx plug in processor
|
|
dd 0e1159h ; CPQ59xx plug in processor
|
|
dd 0e115bh ; CPQffxx plug in processor
|
|
dd 0e1115h ; CPQ15xx (smp version)
|
|
dd 0e1152h ; CPQ15xx (smp version)
|
|
dd 0e1108h ; CPQ15xx
|
|
dd 0592a0h ; ALRa0xx PowerPro
|
|
dd 0592b0h ; ALRb0xx PowerPro plug in processor
|
|
dd 047232h ; Acer SP clone (4p version)
|
|
dd 246c00h ; ICL MX
|
|
dd 246c02h ; ICL (acer 700xx)
|
|
dd 352310h ; Micronycs MPro motherboard
|
|
dd 352311h ; Micronycs MPro
|
|
dd 0592a1h ; ALRa1xx PowerPro (DX2-66 mobo)
|
|
dd 0592a2h ; ALRa2xx PowerPro (reserved mobos)
|
|
dd 0592b1h ; ALRb1xx PowerPro (reserved p2's)
|
|
dd 4dc901h ; Siemens Nixdorf PCE-4T/33
|
|
dd 4dc950h ; Siemens Nixdorf PCE-4T/33
|
|
dd 047219h ; AcerFrame 700
|
|
dd 047232h ; AcerFrame 3000MP560
|
|
dd 0h
|
|
CPUTABLE_SIZE equ ($-spSystemCpuTable)/4
|
|
|
|
; Types match up to CpuTable.
|
|
spSystemTypeTable db SMP_SYSPRO1 ; CPQ01xx 386 ASP
|
|
db SMP_SYSPRO1 ; CPQ11xx 486 ASP
|
|
db SMP_SYSPRO1 ; CPQ50xx plug in processor
|
|
db SMP_SYSPRO1 ; CPQ59xx plug in processor
|
|
db SMP_SYSPRO1 ; CPQffxx plug in processor
|
|
db SMP_SYSPRO2 ; CPQ15xx (smp version)
|
|
db SMP_SYSPRO2 ; CPQ15xx (smp version)
|
|
db SMP_SYSPRO1 ; CPQ15xx
|
|
db SMP_SYSPRO1 ; ALRa0xx PowerPro
|
|
db SMP_SYSPRO1 ; ALRb0xx PowerPro
|
|
db SMP_ACER ; Acer SP clone (4p version)
|
|
db SMP_ACER ; ICL MX
|
|
db SMP_ACER ; ICL (acer 700xx)
|
|
db SMP_SYSPRO1 ; Micronycs MPro motherboard
|
|
db SMP_SYSPRO1 ; Micronycs MPro
|
|
db SMP_SYSPRO1 ; ALRa1xx PowerPro (DX2-66 mobo)
|
|
db SMP_SYSPRO1 ; ALRa2xx PowerPro (reserved mobos)
|
|
db SMP_SYSPRO1 ; ALRb1xx PowerPro (reserved p2's)
|
|
db SMP_SYSPRO1 ; Siemens Nixdorf PCE-4T/33
|
|
db SMP_SYSPRO1 ; Siemens Nixdorf PCE-4T/33
|
|
db SMP_ACER ; AcerFrame 700
|
|
db SMP_ACER ; AcerFrame 3000MP560
|
|
|
|
TYPETABLE_SIZE equ ($-spSystemTypeTable)
|
|
.errnz (CPUTABLE_SIZE - TYPETABLE_SIZE - 1)
|
|
|
|
;
|
|
; Order to check eisa ports in..
|
|
;
|
|
SpPortOrder dw 0000, 0F000h, 0C000h, 0D000h, -1
|
|
|
|
public _SpType, _SpCpuCount, _SpProcessorControlPort
|
|
_SpType db -1 ; Lowest SMP_SYSPRO type found
|
|
_SpCpuCount db 0 ; # of Cpus found
|
|
_SpProcessorControlPort dw 00000h+PCR_OFFSET
|
|
dw 0F000h+PCR_OFFSET
|
|
dw 0C000h+PCR_OFFSET
|
|
dw 0D000h+PCR_OFFSET
|
|
RestoreESP dd 0
|
|
RestoreESP1 dd 0
|
|
SpCOMPAQ db 'COMPAQ'
|
|
SpEISA db 'EISA'
|
|
Sp80386 db '80386'
|
|
Sp80486 db '80486'
|
|
|
|
_DATA ends
|
|
|
|
page ,132
|
|
_TEXT SEGMENT DWORD PUBLIC 'CODE'
|
|
ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
|
|
|
|
;++
|
|
; BOOLEAN
|
|
; DetectSystemPro (
|
|
; OUT PBOOLEAN IsConfiguredMp
|
|
; );
|
|
;
|
|
; Routine Description:
|
|
; This function is only called on EISA machines
|
|
;
|
|
; Determines the type of system (specifically for eisa machines).
|
|
;
|
|
; Arguments:
|
|
; IsConfiguredMp - If the machine is a SystemPro, then this value is
|
|
; set to TRUE if it's an MP SystemPro, else FALSE.
|
|
;
|
|
; Return Value:
|
|
; FALSE - not a supported machine for this HAL
|
|
; TRUE - is SystemPro
|
|
; etc...
|
|
;
|
|
;--
|
|
cPublicProc _DetectSystemPro ,1
|
|
|
|
push edi
|
|
push esi
|
|
push ebx ; Save C Runtime
|
|
|
|
movzx edx, SpPortOrder[0] ; Check system board for
|
|
call CheckEisaCard ; SystemPro belize ID
|
|
if 0
|
|
or eax, eax
|
|
jz dsp_idnotknown
|
|
endif
|
|
cmp al, SMP_SYSPRO2
|
|
je dsp_belize ; if belize, go count belize style
|
|
|
|
xor ebx, ebx ; CpuCount
|
|
xor esi, esi ; Base EisaCard address
|
|
|
|
dsp10: movzx edx, SpPortOrder[esi*2]
|
|
cmp dx, -1 ; End of list?
|
|
je short dsp30 ; Yes, done
|
|
|
|
call CheckEisaCard ; Check Eisa card for cpu
|
|
or eax, eax ; If not cpu, then skip it
|
|
jz short dsp20
|
|
|
|
cmp _SpType, al
|
|
jc @f
|
|
mov _SpType, al ; SpType = min(SpType, eax)
|
|
@@:
|
|
cmp ebx, 4 ; MaxSupported CPUs already found?
|
|
jae dsp20 ; Yes, then skip this one
|
|
|
|
movzx edx, SpPortOrder[esi*2]
|
|
add edx, PCR_OFFSET
|
|
mov _SpProcessorControlPort[ebx*2], dx
|
|
|
|
inc ebx ; CpuCount += 1
|
|
|
|
dsp20: inc esi ; Next EisaCard I/O addr to check
|
|
jmp short dsp10
|
|
|
|
dsp30: xor eax, eax ; Assume FALSE
|
|
ifdef SETUP
|
|
cmp bl, 2 ; Did we find at least 2 CPUs?
|
|
else
|
|
cmp bl, 1 ; Did we find at least 1 CPU?
|
|
endif
|
|
jc short SpExit ; No, then exit
|
|
|
|
mov _SpCpuCount, bl
|
|
mov al, 1 ; return non-zero
|
|
|
|
mov ebx, dword ptr [esp+16]
|
|
mov byte ptr [ebx], al ; *IsConfiguredMp = TRUE
|
|
|
|
SpExit: pop ebx
|
|
pop esi
|
|
pop edi
|
|
stdRET _DetectSystemPro
|
|
|
|
;-----
|
|
|
|
dsp_belize:
|
|
mov _SpType, al ; SpType = SYSPRO2
|
|
|
|
;
|
|
; Put Belize SystemPro into Symmetric mode
|
|
;
|
|
|
|
mov dx, SMP_MODE_PORT
|
|
mov al, SMP_SYMMETRICAL_MODE
|
|
out dx, al
|
|
|
|
;
|
|
; Count CPUs, belize style. And assign logcal IDs to CPUs
|
|
;
|
|
xor ecx,ecx ;physical cpu
|
|
xor ebx,ebx ;logical cpu
|
|
|
|
dsp50:
|
|
mov dx,SMP_INDEX_PORT
|
|
mov al,cl ; al = physical CPU slot number
|
|
out dx, al ; select physical CPU slot in al
|
|
mov dx,SMP_ASSIGNMENT_PORT
|
|
in al,dx ; read CPU number
|
|
cmp al,SMP_MAX_PROCESSORS ; Q:Valid CPU?
|
|
jae short dsp60 ; n:Check next physical CPU slot
|
|
mov al,bl ; y:Make physical CPU a logical CPU
|
|
out dx,al
|
|
inc ebx ; next logical CPU to assign
|
|
dsp60:
|
|
inc ecx ; next physical CPU slot to check
|
|
cmp ecx,SMP_MAX_PROCESSORS
|
|
jb short dsp50 ; look in next cpu slot
|
|
|
|
jmp short dsp30 ; ebx = number of cpus found
|
|
|
|
;-----
|
|
if 0 ; Note: this code is not fully working (did not pass hct's)
|
|
public dsp_idnotknown
|
|
dsp_idnotknown:
|
|
;
|
|
; The eisa ID was not recongonized - attempt to use the protect mode
|
|
; int-15 interface to determine if this is a SystemPro compatible
|
|
; computer. Any SystemPro detected in this manner is assumed to
|
|
; be of type SMP_SYSPRO1 which only has 2 processors.
|
|
;
|
|
; Note: There is a fair amount of paranoia in the following code
|
|
; becuase we trust the rom as little as possible.
|
|
;
|
|
|
|
xor eax, eax
|
|
xor ecx, ecx
|
|
mov cx, ss ; Verify SS value is what it is
|
|
cmp ecx, KGDT_R0_DATA ; expect it to be; otherwise this code
|
|
jne short SpExit ; can't work
|
|
|
|
pushf ; Save current DF & EF
|
|
|
|
sub esp, 15*8
|
|
sidt fword ptr [esp] ; get IDT address
|
|
mov esi, dword ptr [esp+2] ; (esi) = IDT
|
|
mov edi, esp ; (edi) = address to copy vectors to
|
|
|
|
push es ; Save selectors in case rom
|
|
push ds ; trashes state
|
|
push fs
|
|
push gs
|
|
push esi
|
|
push ebp
|
|
cld
|
|
cli
|
|
pushf
|
|
|
|
;
|
|
; Save and hook some IDT vectors. If we get some type of trap
|
|
; here or in the rom, then we will restore the state and return
|
|
; back that a systempro was not detected
|
|
;
|
|
|
|
mov eax, esi
|
|
mov ecx, 15*8/4
|
|
rep movsd ; Save IDT vectors
|
|
|
|
mov RestoreESP, esp ; Save current ESP for restore
|
|
|
|
mov ecx, offset FLAT:dsp_handlefault
|
|
mov dx, cs
|
|
shl edx, 16
|
|
mov dx, cx
|
|
mov cx, 08E00h ; Install int32 gate for vectors
|
|
|
|
mov [eax+0*8+0] , edx
|
|
mov [eax+0*8+4] , ecx ; Trap IDT 0 Divide Error
|
|
mov [eax+4*8+0] , edx
|
|
mov [eax+4*8+4] , ecx ; Trap IDT 4 INTO
|
|
mov [eax+5*8+0] , edx
|
|
mov [eax+5*8+4] , ecx ; Trap IDT 5 BOUND
|
|
mov [eax+6*8+0] , edx
|
|
mov [eax+6*8+4] , ecx ; Trap IDT 6 Invalid OpCode
|
|
mov [eax+11*8+0], edx
|
|
mov [eax+11*8+4], ecx ; Trap IDT 11 Segment not present
|
|
mov [eax+12*8+0], edx
|
|
mov [eax+12*8+4], ecx ; Trap IDT 12 Stack fault
|
|
mov [eax+13*8+0], edx
|
|
mov [eax+13*8+4], ecx ; Trap IDT 13 GP fault
|
|
mov [eax+14*8+0], edx
|
|
mov [eax+14*8+4], ecx ; Trap IDT 14 Page fault
|
|
|
|
;
|
|
; Map in 64K of the ROM in order to use protect mode int-15 interface.
|
|
; (see Compaq eisa spec)
|
|
;
|
|
stdCall _HalpMapPhysicalMemory, <0f0000h, 16> ; map 64K of ROM
|
|
mov ebp, eax ; save ROM starting address
|
|
|
|
;
|
|
; Verify there is a ROM, search for the word 'COMPAQ' in the ROM
|
|
; addresses FE000-FE0FF. (see Compaq eisa spec)
|
|
;
|
|
lea esi, SpCOMPAQ ; 'COMPAQ'
|
|
mov ebx, 6 ; strlen ('COMPAQ')
|
|
lea edi, [ebp+0e000h] ; address to scan
|
|
mov ecx, 0ffh ; length of scan
|
|
call SpScanForString
|
|
jne dsp_handlefault ; if not found then abort
|
|
|
|
;
|
|
; Also verify the 'EISA' work at rom address FFFD0-FFFFF
|
|
; (see Compaq eisa spec)
|
|
;
|
|
lea esi, SpEISA ; 'EISA'
|
|
mov ebx, 4 ; strlen ('EISA')
|
|
lea edi, [ebp+0ffd0h] ; address to scan
|
|
mov ecx, 02fh ; length of scan
|
|
call SpScanForString
|
|
jne dsp_handlefault ; if not found then abort
|
|
|
|
;
|
|
; Look in slot 11 and slot 15 for processors
|
|
;
|
|
sub esp, 400 ; make space for Config Data Block
|
|
mov ecx, 11 ; check slot 11 first
|
|
xor ebx, ebx ; assume no processors found
|
|
|
|
dsp_95:
|
|
push ebp ; save virtual rom address
|
|
push ecx ; save current slot #
|
|
push ebx ; save # processors found
|
|
|
|
xor eax, eax
|
|
lea edi, [esp+12]
|
|
mov ecx, 300/4
|
|
rep stosd ; clear destionation buffer
|
|
|
|
mov ax, 0D881h ; Read Config Info, 32bit
|
|
lea esi, [esp+12] ; destionation address
|
|
|
|
mov RestoreESP1, esp ; Some roms don't iret correctly
|
|
sub esp, 10h ; Some roms clobber some stack
|
|
pushf
|
|
push cs
|
|
lea ebx, [ebp+0f859h] ; 'industry standard' int-15 address
|
|
call ebx ; INT-15 (trashes most registers)
|
|
mov esp, RestoreESP1 ; restore ESP
|
|
jc short dsp_110 ; Not valid, check next slot
|
|
|
|
;
|
|
; Check type field
|
|
;
|
|
lea edi, [esp+12+23h] ; address of type string
|
|
lea esi, Sp80386 ; '80386'
|
|
mov ebx, 5 ; strlen ('80386')
|
|
mov ecx, 80
|
|
call SpScanForString
|
|
je short dsp_105
|
|
|
|
lea edi, [esp+12+23h] ; address of type string
|
|
lea esi, Sp80486 ; '80486'
|
|
mov ebx, 5 ; strlen ('80486')
|
|
mov ecx, 80
|
|
call SpScanForString
|
|
jne short dsp_110
|
|
|
|
dsp_105:
|
|
; string was either 80386 or 80486
|
|
inc dword ptr [esp] ; count one more processor
|
|
|
|
dsp_110:
|
|
pop ebx ; (ebx) = number processors found
|
|
pop ecx ; (ecx) = slot #
|
|
pop ebp ; (ebp) = virtual rom address
|
|
|
|
or ebx, ebx ; if a processor is not in the first
|
|
jz short dsp_handlefault ; slot, then don't look in second
|
|
|
|
cmp ebx, 2 ; if # of processors is trash
|
|
ja short dsp_handlefault ; then abort
|
|
|
|
mov eax, ecx
|
|
cmp eax, 11 ; Did we just test slot 11?
|
|
mov ecx, 15
|
|
je dsp_95 ; Yes, now test 15
|
|
cmp eax, 15 ; Did we just test slot 15?
|
|
je short dsp_cleanup ; Yes, then we are done
|
|
|
|
; slot # isn't 11 or 15, abort
|
|
|
|
dsp_handlefault: ; Sometype of fault, or abort
|
|
mov eax, KGDT_R0_DATA ; make sure ss has the correct value
|
|
mov ss, ax
|
|
xor ebx, ebx ; No processors found
|
|
|
|
dsp_cleanup:
|
|
; (ebx) = # of processors
|
|
mov esp, SS:RestoreESP ; Make sure esp is correct
|
|
|
|
popf
|
|
pop ebp
|
|
pop edi ; (edi) = IDT address
|
|
pop gs ; restore selectors
|
|
pop fs
|
|
pop ds
|
|
pop es
|
|
mov esi, esp ; (esi) = original IDT vectors
|
|
mov ecx, 15*8/4
|
|
rep movsd ; restore IDT vectors
|
|
add esp, 15*8 ; cleanup stack
|
|
popf
|
|
|
|
mov _SpType, SMP_SYSPRO1 ; assume original systempro
|
|
|
|
cmp ebx, 2 ; at least 2 processors found?
|
|
jc short dsp_150 ; no, continue
|
|
;
|
|
; Verify that the second processor board is enabled
|
|
;
|
|
movzx edx, SpPortOrder[1*2]
|
|
add edx, EBC_OFFSET ; (edx) = 0zC84
|
|
in al, dx ; Read control bits
|
|
test al, 1 ; Is Eisa CPU board enabled?
|
|
jnz short dsp_150 ; Yes, continue
|
|
dec ebx ; don't count it
|
|
|
|
dsp_150:
|
|
jmp dsp30 ; exit
|
|
endif
|
|
|
|
stdENDP _DetectSystemPro
|
|
|
|
;++
|
|
; SpScanForString
|
|
;
|
|
; Routine Description:
|
|
; Scans address range looking for matching string
|
|
;
|
|
; Arguments:
|
|
; (edi) = Start of address range to scan
|
|
; (ecx) = Length of address range
|
|
; (esi) = String to scan for
|
|
; (ebx) = Length of string
|
|
;
|
|
; Returns:
|
|
; ZR - String found
|
|
; NZ - String not found
|
|
;
|
|
;--
|
|
SpScanForString proc
|
|
sub ecx, ebx ; don't go past end
|
|
inc ecx
|
|
|
|
mov al, [esi] ; (al) = first char to scan for
|
|
inc esi ; skip past first char
|
|
dec ebx
|
|
|
|
ss10: repne scasb ; look for first byte
|
|
jecxz short ss20 ; byte found? No, exit
|
|
|
|
push ecx
|
|
push edi
|
|
push esi
|
|
mov ecx, ebx ; length of string to compare
|
|
repe cmpsb ; is string at this location?
|
|
or ecx, ecx ; ZF if strings match
|
|
pop esi
|
|
pop edi
|
|
pop ecx
|
|
|
|
jnz short ss10 ; continue looking
|
|
ret ; ZR
|
|
|
|
ss20: inc ecx ; NZ
|
|
ret
|
|
|
|
SpScanForString endp
|
|
|
|
|
|
;++
|
|
; CheckEisaCard
|
|
;
|
|
; Routine Description:
|
|
; Used only by DetectSystemPro.
|
|
;
|
|
; Arguments:
|
|
; (edx) = Eisa ID port to check
|
|
;
|
|
; Returns:
|
|
; (eax) = 0 card was not a valid cpu
|
|
; non-zero Cpu type
|
|
;
|
|
;--
|
|
CheckEisaCard proc
|
|
push edi
|
|
push esi
|
|
push ebx
|
|
|
|
mov esi, edx
|
|
add edx, PRODUCT_ID_OFFSET ; Product ID port
|
|
|
|
xor eax, eax
|
|
in al, dx ; 0zC80
|
|
test al, 80h ; if bit 8 off?
|
|
jnz short NoMatch ; no, then not an Eisa card
|
|
|
|
shl eax, 8
|
|
inc edx
|
|
in al, dx ; 0zC81
|
|
shl eax, 8
|
|
inc edx
|
|
in al, dx ; (eax)=dword of ports 0zC80-0zC82
|
|
|
|
mov ecx, CPUTABLE_SIZE ; Scan CPU table looking for
|
|
lea edi, spSystemCpuTable ; matching board ID
|
|
repne scasd
|
|
jecxz short NoMatch ; Was it found?
|
|
|
|
sub ecx, CPUTABLE_SIZE-1
|
|
neg ecx ; (ecx) = index CPU was found at
|
|
movzx ecx, byte ptr spSystemTypeTable[ecx]
|
|
|
|
or esi, esi ; SystemBoard?
|
|
jz short @f ; Yes, then it is assumed enabled
|
|
|
|
cmp cl, SMP_ACER ; If acer, assume it's enabled
|
|
je short @f ; (machine incorrectly reports
|
|
; 'disable' on every other proc)
|
|
mov edx, esi
|
|
add edx, EBC_OFFSET ; (edx) = 0zC84
|
|
in al, dx ; Read control bits
|
|
test al, 1 ; Is Eisa CPU board enabled?
|
|
jz short NoMatch ; No, then skip it
|
|
@@:
|
|
mov eax, ecx
|
|
jmp short cei_exit
|
|
NoMatch:
|
|
xor eax, eax
|
|
cei_exit:
|
|
pop ebx
|
|
pop esi
|
|
pop edi
|
|
ret
|
|
|
|
CheckEisaCard endp
|
|
|
|
_TEXT ENDS
|