📄 gxmsize.asm
字号:
mov di, CPU_MC_BANK_CFG
mov es:[edi], edx ; Put in new page setting
DO_REFRESH
shr si, 1 ; Divide test address by 2
jmp pageSizeLoop
pageSizeFound:
mov eax, DIMM0_PAGE_CLR
rol eax, cl
and ebp, eax ; Clear page field
mov eax, ebx ; Save bx for next step
shl eax, cl ; Compensate for Dimm
or ebp, eax ; Set page field
;
; Component Banks 1=4 0=2
; Default for Dimm under test = 1
; Default for Dimm not under test = 0
; How it works: The default is for 4 component banks. Since the min page
; size is 1KB, set the test address to be 2KB, which is the 1st byte of the
; 3rd component bank. Then multiply this by the page size just calculated.
; If data wraps at this address then there are only 2 component banks and the
; bit in MC_BANK_CFG can be reset to reflect 2 component banks.
;
shl ecx, 16 ; Save DSV
shr bx, 4 ; Calc page size to low nibble
mov esi, 0800h ; Page=1KB * compbank=2
mov cl, bl ; Use actual page size just
shl esi, cl ; calc to set test address
shr ecx, 16 ; Restore DSV
compBanks:
mov DWORD PTR es:[0], TEST_DATA1 ; Write to location 0
mov DWORD PTR es:[esi], TEST_DATA2 ; Write to top of page
mov DWORD PTR es:[100h], 0 ; Clear the bus
mov eax, DWORD PTR es:[0] ; Read location 0
compVerify:
cmp eax, TEST_DATA1 ; If TOP data, wrap occured
je compBanks4 ; If no wrap then leave 4 comp banks
mov eax, DIMM0_COMP_CLR
rol eax, cl
and ebp, eax ; Comp bank = 2
and edx, eax ; EDX value for CPU_MC_BANK_CFG
mov di, CPU_MC_BANK_CFG
mov es:[edi], edx ; Put in comp bank setting
DO_REFRESH
jmp moduleBanksCheck
compBanks4:
mov eax, DIMM0_COMP_SET
rol eax, cl
or ebp, eax ; Comp bank = 4
;
; Module Banks 1=2 0=1
; Default for Dimm under test = 1
; Default for Dimm not under test = 0
; How it works: The Dimm is set for 2 Module Banks. A write is done to the
; 2nd module bank. The offset to write too is computed by knowing the page
; size that has been computed and the number of component banks. So the next
; address would go to the second module bank if it exists. If the data cannot
; be read back then it is assumed that there is no second module bank
; and the value is set to 0 in theMC_ BANK_CFG register
;
moduleBanksCheck:
mov esi, 0800h ; Min 1K page x 2 comp banks
mov eax, edx ; Isolate the page size
shr eax, cl
shr ax, 4
and al, 7h
shl ecx, 16
mov cl, al
shl esi, cl ; Multiply by actual page size
shr ecx, 16
mov eax, edx ; Isolate comp banks
shr eax, cl
shr ax, 12
and ax, 1
shl ecx, 16
mov cl, al
shl esi, cl ; If 4 comp banks x by 2
shr ecx, 16
moduleBanks:
mov DWORD PTR es:[0], TEST_DATA1 ; Write to location 0
mov DWORD PTR es:[esi], TEST_DATA2 ; Attempt write to mod bank 2
mov DWORD PTR es:[100h], 0 ; Clear the bus
mov eax, DWORD PTR es:[esi] ; Read location in 2nd Module
moduleVerify:
cmp eax, TEST_DATA2 ; If good data then 2nd mod bank
je moduleBanks2 ; Leave set to 2 mod banks
mov eax, DIMM0_MODULE_CLR
rol eax, cl
and ebp, eax ; Module bank = 1
and edx, eax ; EDX value for BANK_CFG
mov di, CPU_MC_BANK_CFG
mov es:[edi], edx ; Put in module bank setting
DO_REFRESH
jmp dimmSize
moduleBanks2:
mov eax, DIMM0_MODULE_SET
rol eax, cl
or ebp, eax ; Module bank = 2
;
; DIMM Size 0=4MB 1=8MB 2=16MB 3=32MB 4=64MB 5=128MB 6=256MB 7=512MB
; Default for Dimm under test = 7
; Default for Dimm not under test = 0
;
; How it works: We now know the page size, component banks and module banks.
; For this test just start at 512 MB and a test address of 1/2 of that. If
; the write aliases then the size is smaller. So keep dividing by 2 until
; the alias goes away. The value last held in ebx is the value to program
; the dimm size field in MC_BANK_CFG
;
dimmSize:
mov ebx, 0700h ; Represents 512MB
mov esi, 10000000h ; Start at 256MB boundary
dimmSizeLoop:
mov DWORD PTR es:[0], TEST_DATA1 ; Write to location 0
mov DWORD PTR es:[esi], TEST_DATA2 ; Write to TOP/2
mov DWORD PTR es:[100h], 0 ; Clear the bus
mov eax, DWORD PTR es:[0] ; Read location 0
dimmSizeVerify:
cmp eax, TEST_DATA1 ; If TOP/2 data, wrap occured
je dimmSizeFound
mov di, CPU_MC_BANK_CFG
mov edx, es:[edi] ; BANK_CFG setting in edx
mov eax, DIMM0_SIZE_CLR
rol eax, cl
and edx, eax ; Clear page field
dec ebx
cmp bh, 0FFh ; Went thru all combo's
je failedID
and ebx, 700h ; Must be {0..7}
shl ebx, cl ; Move to Dimm word in reg
or edx, ebx
shr ebx, cl
mov di, CPU_MC_BANK_CFG
mov es:[edi], edx ; Put in new size setting
DO_REFRESH
shr esi, 1 ; Divide test address by 2
jmp dimmSizeLoop
dimmSizeFound:
mov eax, DIMM0_SIZE_CLR
rol eax, cl
and ebp, eax ; Clear dimm size field
shl ebx, cl ; Compensate for Dimm
or ebp, ebx ; Set dimm size field
jmp tryNextDimm
failedID:
mov eax, 0FFFF0000h ; Could not determine page
rol eax, cl ; size or DIMM size
and ebp, eax
mov eax, DIMM_MISSING
shl eax, cl
or ebp, eax ; Indicate not installed
tryNextDimm:
mov DWORD PTR es:[0], 12345678h
jmp tryDimm1 ; Check next dimm
doneSizing:
stc ; Assume no Dimms installed
cmp ebp,00700070h
je exitSizing ; No Dimms so leave carry set
clc
exitSizing:
mov bx, gs ; Restore return address
jmp bx
csSdramAutoSize ENDP
;**************************************************************************
;*
;* csGeodeGetMmrBase
;*
;* Get Memory-Mapped Register Base Address (STACKLESS)
;*
;* Entry:
;* None
;*
;* Exit:
;* EDI - Base of memory mapped Cpu registers
;*
;* Destroys:
;*
;**************************************************************************
csGeodeGetMmrBase PROC NEAR PUBLIC
;MAPEN MUST ALREADY BE ENABLED
mov al, CPU_GXI_GCR
out CPU_INDEX, al
in al, CPU_DATA ; Read upper 2 addr bits from GCR reg in core
shl eax, 30
mov edi, eax
jmp bx
csGeodeGetMmrBase ENDP
;**************************************************************************
;*
;* CpuMemRegRead
;*
;* Read Data (DWORD) from Config Register (STACKLESS)
;*
;* Entry:
;* EAX - Register Index
;* BX - Return Address
;*
;* Exit:
;* EAX - Register Index
;* EDX - Register Data
;* BX - Return Address
;*
;* Destroys: EDI
;*
;**************************************************************************
CpuMemRegRead PROC NEAR PUBLIC
;
; Generate an SMI to write the GX registers
;
and eax, 0000FFFFh ; Clear EAX[31:16]
mov edi, eax ; Save EAX
mov al, CPU_CCR1
out CPU_INDEX, al
in al, CPU_DATA ; VSA turns on USE_SMI. If USE_SMI is 0 then skip Soft SMI access.
test al, 02h
jz csRegReadMemMap
mov dx, 0CF8h ; PCI Index
mov eax, 800090D0h ; MediaGxi PFA
out dx, eax
mov eax, edi ; Restore EAX
shl eax, 16 ; Save ax to upper eax
mov dx, 0CFCh
mov ax, -3 ; Read operation
stc ; Assume read operation fails
out dx, ax ; Generate software SMI
out 0EDh, al ; Do NOT remove, required for SMI to work.
nop ; Delay
jc csRegReadMemMap ; Use alternative register access
; mechanism if VSA inactive
mov edx, eax ; EAX = Data Read
mov eax, edi ; Restore EAX
jmp bx ; Return to caller
csRegReadMemMap:
mov eax, edi ; Restore register index
; MAPEN MUST ALREADY BE ENABLED
mov al, CPU_GXI_GCR
out CPU_INDEX, al
in al, CPU_DATA ; Read upper 2 addr bits from GCR
shl eax, 30
mov ax, di ; Calculate address of register
; check if register is less than 8000h if so add 10000h to address
; this is so we behave like the software smi
.IF (ax < 8000h)
add eax,00010000h
.ENDIF
mov edx, es:[eax] ; Read data from register
mov eax, edi ; Restore EAX
jmp bx
CpuMemRegRead ENDP
;**************************************************************************
;*
;* CpuMemRegWrite
;*
;* Write Data (DWORD) to Config Register (STACKLESS)
;*
;* Entry:
;* EAX - Register Index
;* EDX - Register Data
;* BX - Return Address
;*
;* Exit:
;* EAX - Register Index
;* EDX - Register Data
;* BX - Return Address
;*
;* Destroys:
;* EDI
;*
;**************************************************************************
CpuMemRegWrite PROC NEAR PUBLIC
;
; Generate an SMI to write the Geode registers
;
and eax, 0000FFFFh ; Clear EAX[31:16]
mov edi, edx ; Save register data
shl eax, 16 ; Save register index
mov edx, eax ; Save register index to upper edx
mov al, CPU_CCR1
out CPU_INDEX, al
in al, CPU_DATA ; VSA turns on USE_SMI. If USE_SMI is 0 then skip Soft SMI access.
test al, 02h
jz csRegWriteMemMap
mov dx, 0CF8h ; PCI Index
mov eax, 800090D0h ; MediaGxi PFA
out dx, eax
mov eax, edx ; Restore register index
mov dx, 0CFCh
mov ax, -4 ; Write operation
stc ; Assume write operation fails
out dx, ax ; Generate software SMI
out 0EDh, al ; Do NOT remove, required for SMI to work.
nop ; Delay
jc csRegWriteMemMap ; Use alternative register access
; mechanism if VSA inactive
mov edx, edi ; Restore register data
shr eax, 16 ; Restore register index
jmp bx ; Return to caller
csRegWriteMemMap:
shr eax, 16 ; Restore register index
mov edx, edi ; EDX <- Register Data
mov edi, eax ; Save register index
; MAPEN MUST ALREADY BE ENABLED
mov al, CPU_GXI_GCR
out CPU_INDEX, al
in al, CPU_DATA ; Read upper 2 addr bits from GCR
shl eax, 30
mov ax, di ; Calculate address of register
; check if register is less than 8000h if so add 10000h to address
; this is so we behave like the software smi
.IF (ax < 8000h)
add eax,00010000h
.ENDIF
mov es:[eax], edx ; Write data to register
mov eax, edi ; Restore register index
jmp bx
CpuMemRegWrite ENDP
;**************************************************************************
;*
;* CpuMemRegReadStack
;*
;* Read Data (DWORD) from Config Register
;*
;* Entry:
;* EAX - Register Index
;*
;* Exit:
;* EAX - Register Index
;* EDX - Register Data
;*
;* Destroys:
;* None
;*
;**************************************************************************
CpuMemRegReadStack PROC NEAR PUBLIC
push eax
push edi
push es
push bx
NOSTACK bx, CpuMemRegRead
pop bx
pop es
pop edi
pop eax
ret
CpuMemRegReadStack ENDP
;**************************************************************************
;*
;* CpuMemRegWriteStack
;*
;* Write Data (DWORD) to Config Register
;*
;* Entry:
;* EAX - Register Index
;* EDX - Register Data
;*
;* Exit:
;* None
;*
;* Destroys:
;* None
;*
;**************************************************************************
CpuMemRegWriteStack PROC NEAR PUBLIC
push eax
push edx
push edi
push es
push bx
NOSTACK bx, CpuMemRegWrite
pop bx
pop es
pop edi
pop edx
pop eax
ret
CpuMemRegWriteStack ENDP
_TEXT ENDS
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -