Rev 4289 | Rev 4310 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 4289 | Rev 4294 | ||
---|---|---|---|
Line 1... | Line 1... | ||
1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
2 | ;; ;; |
2 | ;; ;; |
3 | ;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;; |
3 | ;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;; |
4 | ;; Distributed under terms of the GNU General Public License ;; |
4 | ;; Distributed under terms of the GNU General Public License ;; |
5 | ;; ;; |
5 | ;; ;; |
6 | ;; 20/11/2013 yogev_ezra: Initial version ;; |
- | |
7 | ;; Thanks for help to: dunkaist, eAndrew, hidnplayr, Mario ;; |
- | |
8 | ;; ;; |
- | |
9 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
6 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
Line -... | Line 7... | ||
- | 7 | ||
- | 8 | ; 20/11/2013 yogev_ezra: Initial version (Vortex86 SoC type detection) |
|
- | 9 | ; 26/11/2013 yogev_ezra: Added CPU speed modifier and MMX support flag detection |
|
- | 10 | ; Thanks for help to: dunkaist, eAndrew, hidnplayr, Mario |
|
10 | 11 | ||
Line 11... | Line 12... | ||
11 | $Revision: 4289 $ |
12 | $Revision: 4294 $ |
12 | 13 | ||
Line 13... | Line 14... | ||
13 | VORTEX86DEBUG = 0 ; For testing in emulators and in non-Vortex86 CPU computers, set this to 1 |
14 | VORTEX86DEBUG = 0 ; For testing in emulators and in non-Vortex86 CPU computers, set this to 1 |
Line 27... | Line 28... | ||
27 | Vortex86CPUid db 0 ; Vortex86 CPU id in integer format (1=Vortex86SX, 2=Vortex86DX, ...) |
28 | Vortex86CPUid db 0 ; Vortex86 CPU id in integer format (1=Vortex86SX, 2=Vortex86DX, ...) |
28 | Vortex86SoCname db 'Vortex86 ',0 ; This variable will hold the full name of Vortex86 SoC |
29 | Vortex86SoCname db 'Vortex86 ',0 ; This variable will hold the full name of Vortex86 SoC |
29 | Vortex86SoClist: ; List of Vortex86 CPUs known today. Add new record to this list when new CPU becomes available |
30 | Vortex86SoClist: ; List of Vortex86 CPUs known today. Add new record to this list when new CPU becomes available |
30 | db 0x31, 'SX ' ; id=1 |
31 | db 0x31, 'SX ' ; id=1 |
31 | db 0x32, 'DX ' ; id=2 |
32 | db 0x32, 'DX ' ; id=2 |
32 | db 0x33, 'MX ' ; id=3 |
33 | db 0x33, 'MX ' ; id=3 MMX is available starting from CPU code 'MX' (id=3) |
33 | db 0x34, 'DX2' ; id=4 |
34 | db 0x34, 'DX2' ; id=4 |
34 | db 0x35, 'MX+' ; id=5 |
35 | db 0x35, 'MX+' ; id=5 |
35 | db 0x37, 'EX ' ; id=6 |
36 | db 0x37, 'EX ' ; id=7 |
36 | Vortex86SoCnum = ($ - Vortex86SoClist) / 4 ; Calculate the total number of known Vortex86 CPUs (if id=Vortex86SoCnum+1 --> unknown SoC) |
37 | Vortex86SoCnum = ($ - Vortex86SoClist) / 4 ; Calculate the total number of known Vortex86 CPUs |
37 | endg |
38 | endg |
Line 38... | Line 39... | ||
38 | 39 | ||
39 | ; When in debug mode, perform SoC detection regardless of the actual CPU vendor (even for vendors other than DMP) |
40 | ; When in debug mode, perform SoC detection regardless of the actual CPU vendor (even for vendors other than DMP) |
40 | ; When in normal (not debug) mode, check the CPU vendor first, and perform SoC detection only if vendor is 'Vortex86 SoC' |
41 | ; When in normal (not debug) mode, check the CPU vendor first, and perform SoC detection only if vendor is 'Vortex86 SoC' |
41 | if ~ VORTEX86DEBUG |
42 | if ~ VORTEX86DEBUG |
42 | cmp [cpu_vendor], 'Vort' |
43 | cmp [cpu_vendor], 'Vort' |
43 | jnz .Vortex86end ; If the CPU vendor is not 'Vortex86 SoC', skip the SoC detection |
44 | jnz .Vortex86end ; If the CPU vendor is not 'Vortex86 SoC', skip the SoC detection |
Line 44... | Line -... | ||
44 | end if |
- | |
45 | 45 | end if |
|
46 | mov dx, 0xcf8 ; CF8h = Vortex86 PCI Configuration Address port |
46 | |
47 | mov eax, OS_BASE+0x90 ; 0x80000090 = Starting PCI address to read from (32-bit register - accessed as DWORD) |
- | |
48 | out dx, eax ; Send request to PCI address port to retrieve data from this address |
- | |
Line 49... | Line 47... | ||
49 | mov dx, 0xcfc ; CFCh = Vortex86 PCI Configuration Data port |
47 | mov eax, OS_BASE+0x90 ; 0x80000090 = Starting PCI address to read from (32-bit register - accessed as DWORD) |
50 | in eax, dx ; Read data (SoC type) from PCI data port |
48 | call .Vortex86PCIreg ; Get the CPU code from Vortex86 SoC PCI register (Register Offset: 93H~90H) |
51 | 49 | ||
Line 52... | Line 50... | ||
52 | if VORTEX86DEBUG ; When in debug mode, pretend that we received port output equal to "VORTEX86DEBUGVALUE" |
50 | if VORTEX86DEBUG ; When in debug mode, pretend that we received port output equal to "VORTEX86DEBUGVALUE" |
53 | mov eax, VORTEX86DEBUGVALUE |
51 | mov eax, VORTEX86DEBUGVALUE |
54 | end if |
52 | end if |
55 | 53 | ||
56 | DEBUGF 1, "K : Vortex86 SoC register returned 0x" |
54 | DEBUGF 1, "K : Vortex86 SoC type register (93H~90H) returned 0x" |
Line 57... | Line 55... | ||
57 | test eax, eax ; Check whether the port output was '\0' |
55 | test eax, eax ; Check whether the port output was '\0' |
58 | jz .nullPCIoutput ; In case the result is '\0' (NULL), skip further testing and exit |
56 | jz .nullPCIoutput ; In case the result is '\0' (NULL), skip further testing and exit |
59 | mov [Vortex86CPUcode], eax ; Save HEX CPU code to Vortex86CPUcode (so it can be used later) |
57 | mov [Vortex86CPUcode], eax ; Save HEX CPU code to Vortex86CPUcode (so it can be used later) |
60 | DEBUGF 1, "%x (%s): ", eax, Vortex86CPUcode ; Print the CPU code (as HEX and as string) to debug log |
58 | DEBUGF 1, "%x (%s): ", eax, Vortex86CPUcode ; Print the CPU code (as HEX and as string) to debug log |
61 | 59 | ||
- | 60 | mov ebx, 0x444d5000 ; Apply Vortex86 CPU code mask (all Vortex86 SoC have ID in form of "0xNN504d44") |
|
- | 61 | bswap eax ; Assumed it is Vortex86 SoC, the highest byte identifies the exact CPU, so move it to the lowest byte |
|
- | 62 | mov bl, al ; Copy SoC type to BL since EAX (that includes AL) is used implicitly in "LODSD" command below |
|
Line 62... | Line 63... | ||
62 | mov ebx, 0x444d5000 ; Apply Vortex86 CPU code mask (all Vortex86 SoC have ID in form of "0xNN504d44") |
63 | cmp eax, ebx ; Now see whether the 3 higher bytes were "0x504d44" (which means it's Vortex86) |
63 | bswap eax ; Assumed it is Vortex86 SoC, the highest byte identifies the exact CPU, so move it to the lowest byte |
64 | jnz .notVortex86 ; If it's not Vortex86 - go say so and exit |
64 | mov bl, al ; Copy SoC type to BL since EAX (that includes AL) is used implicitly in "LODSD" command below |
65 | |
65 | cmp eax, ebx ; Now see whether the 3 higher bytes were "0x504d44" (which means it's Vortex86) |
66 | sub al, 0x30 ; Current Vortex86 CPU codes are in the range of 31h-37h, so convert them to integer (1,2,...) |
Line 76... | Line 77... | ||
76 | cmp bl, al ; Check if our CPU matches the current record in the list |
77 | cmp bl, al ; Check if our CPU matches the current record in the list |
77 | jne @b ; No match --> repeat with next record |
78 | jne @b ; No match --> repeat with next record |
Line 78... | Line 79... | ||
78 | 79 | ||
79 | shr eax, 8 ; Match found --> drop the SoC type code from Vortex86SoClist name and replace it with \0 |
80 | shr eax, 8 ; Match found --> drop the SoC type code from Vortex86SoClist name and replace it with \0 |
80 | mov dword [Vortex86SoCname+8], eax ; Concatenate it with prefix to receive complete SoC name (\0 is string termination) |
- | |
- | 81 | mov dword [Vortex86SoCname+8], eax ; Concatenate it with prefix to receive complete SoC name (\0 is string termination) |
|
81 | mov [Vortex86CPUid], cl ; Save the CPUid (1=Vortex86SX, 2=Vortex86DX, ..., Vortex86SoCnum+1=Unknown Vortex86) |
82 | |
82 | DEBUGF 1, "%s (id=%d)\n", Vortex86SoCname, [Vortex86CPUid]:1 ; Say what we have found (CPU name and id) |
83 | DEBUGF 1, "%s (id=%d)\n", Vortex86SoCname, [Vortex86CPUid]:1 ; Say what we have found (CPU name and id) |
Line 83... | Line 84... | ||
83 | jmp .Vortex86end |
84 | jmp .Vortex86 |
84 | 85 | ||
85 | .notVortex86: ; In case this register is used by other CPUs for other purpose, it's interesting what it contains |
86 | .notVortex86: ; In case this register is used by other CPUs for other purpose, it's interesting what it contains |
Line -... | Line 87... | ||
- | 87 | DEBUGF 1, "not a Vortex86 CPU\n" |
|
- | 88 | jmp .Vortex86end |
|
- | 89 | ||
86 | DEBUGF 1, "not a Vortex86 CPU\n" |
90 | .unknownVortex86: ; It is Vortex86 CPU, but it's not in the list above |
- | 91 | DEBUGF 1, "unknown Vortex86 CPU (id=%d)\n", [Vortex86CPUid]:1 ; Inform the user that the CPU is Vortex86 but name is unknown |
|
- | 92 | ||
- | 93 | .Vortex86: |
|
- | 94 | mov eax, OS_BASE+0xA0 ; 0x800000A0 = Starting PCI address to read from (32-bit register - accessed as DWORD) |
|
- | 95 | call .Vortex86PCIreg ; Get current flags of Vortex86SoC Host Control Register (Register Offset: A3h~A0h) |
|
- | 96 | DEBUGF 1, "K : Vortex86 Host Control Register (A3h~A0h) returned 0x%x: CPU speed is ",eax |
|
- | 97 | mov bl, al ; The lower byte of Vortex86 Host Control Register contains CPU speed modifier and MMX support status |
|
- | 98 | mov bh, al ; Backup the current AL value, so later we can test whether the value has changed |
|
- | 99 | and bl, 00000111b ; CPU speed modifier is stored in bits 0-2. Value=0 means MAX speed, other values - speed reduction |
|
- | 100 | jz .Vortex86CPUspeedMAX ; 0s in bits 0-2: CPU is at MAX speed (no need to modify) |
|
- | 101 | inc bl ; The actual value is 1 less than 'Divide by' setting (value '001' means 'Divide by 2', etc.) |
|
- | 102 | DEBUGF 1, "reduced (divide by %d).\nK : Vortex86 changing CPU speed to ", bl ; Print the current CPU speed modifier to the log |
|
- | 103 | and al, 11111000b ; At least one of the bits 0-2 contains 1: CPU is at reduced speed. Set bits 0-2 to 0s to change to MAX |
|
87 | jmp .Vortex86end |
104 | .Vortex86CPUspeedMAX: |
- | 105 | DEBUGF 1, "MAX\n" ; Now the CPU should be running at MAX speed (don't write the value to PCI port yet) |
|
- | 106 | ||
- | 107 | cmp [Vortex86CPUid], 3 ; MMX is available starting from CPU code 'MX' (id=3) |
|
- | 108 | jb .skipVortex86MMX ; No MMX support - skip MMX support status detection (for id=1,2) |
|
- | 109 | DEBUGF 1, "K : Vortex86 MMX support status: MMX is " ; Bits 5-6 in Host Control Register contain MMX status |
|
- | 110 | test al, 100000b ; On MMX-capable Vortex86 SoC, Bit5 = is MMX enabled? (1=Yes/0=No) |
|
- | 111 | jnz .Vortex86MMXenabled ; MMX is already enabled (Bit5=1) |
|
- | 112 | DEBUGF 1, "DISABLED - enabling it for this session\n" ; Print to the log that MMX is disabled |
|
- | 113 | or al, 100000b ; Enable MMX support (don't write the value to PCI port yet) |
|
- | 114 | jmp .AfterMMXenabled |
|
- | 115 | .Vortex86MMXenabled: |
|
- | 116 | DEBUGF 1, "ENABLED\n" ; Print to the log that MMX is enabled |
|
- | 117 | .AfterMMXenabled: |
|
- | 118 | DEBUGF 1, "K : Vortex86 MMX report to CPUID: " ; Print to the log what CPUID command knowns about MMX support |
|
- | 119 | test al, 1000000b ; On MMX-capable Vortex86 SoC, Bit6 = report MMX support to CPUID? (1=Yes/0=No) |
|
- | 120 | jnz .Vortex86MMXreported ; MMX is already reported to CPUID (Bit6=1) |
|
- | 121 | DEBUGF 1, "OFF - turning it ON for this session\n" ; Print to the log that MMX will now be reported to CPUID |
|
- | 122 | or al, 1000000b ; Turn on MMX reporting to CPUID (don't write the value to PCI port yet) |
|
- | 123 | jmp .skipVortex86MMX |
|
- | 124 | .Vortex86MMXreported: |
|
- | 125 | DEBUGF 1, "ON\n" ; Print to the log that MMX reporting to CPUID is enabled |
|
- | 126 | ||
- | 127 | .skipVortex86MMX: |
|
88 | 128 | cmp bh, al ; Check whether AL has changed before (if it did, we need to write it back to PCI port) |
|
89 | .unknownVortex86: |
129 | jz .Vortex86end ; No change - no need to write to the port |
Line -... | Line 130... | ||
- | 130 | out dx, al ; Write the changed data to PCI port |
|
- | 131 | DEBUGF 1, "K : Vortex86 Host Control Register (A3h~A0h) new value is 0x%x\n",eax |
|
- | 132 | jmp .Vortex86end |
|
- | 133 | ||
- | 134 | .Vortex86PCIreg: ; Procedure receives input register value in EAX, and returns the output value also in EAX |
|
- | 135 | mov dx, 0xcf8 ; CF8h = Vortex86 PCI Configuration Address port |
|
- | 136 | out dx, eax ; Send request to PCI address port to retrieve data from this address |
|
90 | mov [Vortex86CPUid], cl ; Save the CPUid (Vortex86SoCnum+1=Unknown Vortex86) |
137 | mov dl, 0xfc ; CFCh = Vortex86 PCI Configuration Data port |
91 | DEBUGF 1, "unknown Vortex86 CPU (id=%d, last known is %d)\n", [Vortex86CPUid]:1, Vortex86SoCnum |
138 | in eax, dx ; Read data from PCI data port |
Line 92... | Line 139... | ||
92 | jmp .Vortex86end |
139 | ret |
93 | 140 |