Subversion Repositories Kolibri OS

Rev

Rev 4423 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
4265 Serge 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
5565 serge 3
;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;;
4265 Serge 4
;; Distributed under terms of the GNU General Public License    ;;
5
;;                                                              ;;
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7
 
4423 Serge 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
4265 Serge 11
 
4423 Serge 12
$Revision: 4310 $
13
 
4265 Serge 14
VORTEX86DEBUG = 0                       ; For testing in emulators and in non-Vortex86 CPU computers, set this to 1
15
VORTEX86DEBUGVALUE = 0x35504d44         ; FAKE port output = used for testing
4423 Serge 16
NORTH_BRIDGE = 0x80000000               ; Base address of Vortex86 PCI North Bridge
17
SOUTH_BRIDGE = 0x80003800               ; Base address of Vortex86 PCI South Bridge
4265 Serge 18
 
19
; Detect Vortex86 CPU and generate CPU name in string format (PCI address at 93H~90H in Vortex86 North Bridge contains SoC type)
20
; Available Vortex86 CPU codes taken from Coreboot project. New codes should be added to "Vortex86SoClist" below
21
; #define DMP_CPUID_SX      0x31504d44  ("DMP1")
22
; #define DMP_CPUID_DX      0x32504d44  ("DMP2")
23
; #define DMP_CPUID_MX      0x33504d44  ("DMP3")
24
; #define DMP_CPUID_DX2     0x34504d44  ("DMP4")
25
; #define DMP_CPUID_MX_PLUS 0x35504d44  ("DMP5")
26
; #define DMP_CPUID_EX      0x37504d44  ("DMP7")
27
 
28
iglobal
29
Vortex86CPUcode dd ?                    ; Vortex86 CPU code in HEX format (4 bytes), can be shown as string if converted to ASCII characters
30
Vortex86CPUid   db 0                    ; Vortex86 CPU id in integer format (1=Vortex86SX, 2=Vortex86DX, ...)
31
Vortex86SoCname db 'Vortex86   ',0      ; This variable will hold the full name of Vortex86 SoC
32
Vortex86SoClist:                        ; List of Vortex86 CPUs known today. Add new record to this list when new CPU becomes available
33
        db      0x31, 'SX '     ; id=1
34
        db      0x32, 'DX '     ; id=2
4423 Serge 35
        db      0x33, 'MX '     ; id=3  MMX is available starting from CPU code 'MX' (id=3)
4265 Serge 36
        db      0x34, 'DX2'     ; id=4
37
        db      0x35, 'MX+'     ; id=5
4423 Serge 38
        db      0x37, 'EX '     ; id=7
39
Vortex86SoCnum = ($ - Vortex86SoClist) / 4      ; Calculate the total number of known Vortex86 CPUs
4265 Serge 40
endg
41
 
4287 Serge 42
; When in debug mode, perform SoC detection regardless of the actual CPU vendor (even for vendors other than DMP)
43
; When in normal (not debug) mode, check the CPU vendor first, and perform SoC detection only if vendor is 'Vortex86 SoC'
44
if ~ VORTEX86DEBUG
45
        cmp     [cpu_vendor], 'Vort'
46
        jnz     .Vortex86end            ; If the CPU vendor is not 'Vortex86 SoC', skip the SoC detection
4423 Serge 47
end if
4287 Serge 48
 
4423 Serge 49
        mov     eax, NORTH_BRIDGE+0x90  ; 0x80000090 = PCI Configuration Address Register to read from (32-bit register - accessed as DWORD)
50
        call    .Vortex86PCIreg         ; Get the CPU code from Vortex86 SoC North Bridge PCI register (Register Offset: 93H~90H)
4265 Serge 51
 
4287 Serge 52
if VORTEX86DEBUG                        ; When in debug mode, pretend that we received port output equal to "VORTEX86DEBUGVALUE"
4265 Serge 53
        mov     eax, VORTEX86DEBUGVALUE
4423 Serge 54
end if
4265 Serge 55
 
4423 Serge 56
        DEBUGF  1, "K : Vortex86 SoC type register (93H~90H) returned 0x"
57
        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
59
        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
61
 
62
        mov     ebx, 0x444d5000         ; Apply Vortex86 CPU code mask (all Vortex86 SoC have ID in form of "0xNN504d44")
63
        bswap   eax                     ; Assumed it is Vortex86 SoC, the highest byte identifies the exact CPU, so move it to the lowest byte
64
        mov     bl, al                  ; Copy SoC type to BL since EAX (that includes AL) is used implicitly in "LODSD" command below
65
        cmp     eax, ebx                ; Now see whether the 3 higher bytes were "0x504d44" (which means it's Vortex86)
66
        jnz     .notVortex86            ; If it's not Vortex86 - go say so and exit
67
 
68
        sub     al, 0x30                ; Current Vortex86 CPU codes are in the range of 31h-37h, so convert them to integer (1,2,...)
69
        mov     [Vortex86CPUid], al     ; Save the CPUid (1=Vortex86SX, 2=Vortex86DX, ..., 7=Vortex86EX, ...)
70
 
4265 Serge 71
        mov     esi, Vortex86SoClist    ; ESI points to the start of Vortex86SoClist (used implicitly in "LODSD" command below)
72
        xor     ecx, ecx                ; Zero ECX (it is used as counter)
73
        cld                             ; Clears the DF flag in the EFLAGS register (DF=0 --> String operations increment ESI)
74
@@:
4423 Serge 75
        inc     ecx                     ; Increment our counter
4265 Serge 76
        cmp     ecx, Vortex86SoCnum     ; Check if we iterated Vortex86SoCnum times already (i.e. went over the entire Vortex86SoClist)
77
        ja      .unknownVortex86        ; If the entire list was tested and our CPU is not in that list, it is unknown Vortex86 SoC
78
        lodsd                           ; Load DWORD at address DS:ESI into EAX (puts 1 line from Vortex86SoClist into EAX, then increments ESI)
79
        cmp     bl, al                  ; Check if our CPU matches the current record in the list
80
        jne     @b                      ; No match --> repeat with next record
4423 Serge 81
 
4265 Serge 82
        shr     eax, 8                              ; Match found --> drop the SoC type code from Vortex86SoClist name and replace it with \0
83
        mov     dword [Vortex86SoCname+8], eax      ; Concatenate it with prefix to receive complete SoC name (\0 is string termination)
84
 
4423 Serge 85
        DEBUGF  1, "%s (id=%d)\n", Vortex86SoCname, [Vortex86CPUid]:1           ; Say what we have found (CPU name and id)
86
        jmp     .Vortex86
87
 
88
.notVortex86:                           ; In case this register is used by other CPUs for other purpose, it's interesting what it contains
89
        DEBUGF  1, "not a Vortex86 CPU\n"
4265 Serge 90
        jmp     .Vortex86end
4423 Serge 91
 
92
.unknownVortex86:                       ; It is Vortex86 CPU, but it's not in the list above
93
        DEBUGF  1, "unknown Vortex86 CPU (id=%d)\n", [Vortex86CPUid]:1          ; Inform the user that the CPU is Vortex86 but name is unknown
94
 
95
.Vortex86:
96
        mov     eax, NORTH_BRIDGE+0x60  ; 0x80000060 = PCI Configuration Address Register to read from (32-bit register - accessed as DWORD)
97
        call    .Vortex86PCIreg         ; Get current flags of Vortex86SoC North Bridge STRAP Register (Register Offset: 63h~60h)
98
        DEBUGF  1, "K : Vortex86 STRAP Register (63h~60h) returned 0x%x\n",eax
99
 
100
        mov     eax, SOUTH_BRIDGE+0xC0  ; 0x800038C0 = PCI Configuration Address Register to read from (32-bit register - accessed as DWORD)
101
        call    .Vortex86PCIreg         ; Flags of Vortex86 South Bridge Internal Peripheral Feature Control Register (Register Offset: C3h~C0h)
102
        DEBUGF  1, "K : Vortex86 Internal Peripheral Feature Control Register (C3h~C0h) returned 0x%x\n",eax
103
 
104
        mov     eax, SOUTH_BRIDGE+0xCC  ; 0x800038CC = PCI Configuration Address Register to read from (8-bit register - accessed as BYTE)
105
        call    .Vortex86PCIreg         ; Flags of Vortex86 South Bridge Internal Peripheral Feature Control Register III (Register Offset: CCh)
106
        DEBUGF  1, "K : Vortex86 Internal Peripheral Feature Control Register III (CCh) returned 0x%x\n",al
4265 Serge 107
 
4423 Serge 108
        mov     eax, NORTH_BRIDGE+0xA0  ; 0x800000A0 = PCI Configuration Address Register to read from (32-bit register - accessed as DWORD)
109
        call    .Vortex86PCIreg         ; Get current flags of Vortex86SoC North Bridge Host Control Register (Register Offset: A3h~A0h)
110
        DEBUGF  1, "K : Vortex86 Host Control Register (A3h~A0h) returned 0x%x: CPU speed is ",eax
111
        mov     bl, al                  ; The lower byte of Vortex86 Host Control Register contains CPU speed modifier and MMX support status
112
        mov     bh, al                  ; Backup the current AL value, so later we can test whether the value has changed
113
        and     bl, 00000111b           ; CPU speed modifier is stored in bits 0-2. Value=0 means MAX speed, other values - speed reduction
114
        jz      .Vortex86CPUspeedMAX    ; 0s in bits 0-2: CPU is at MAX speed (no need to modify)
115
        inc     ebx                     ; The actual value is 1 less than 'Divide by' setting (value '001' means 'Divide by 2', etc.)
116
        DEBUGF  1, "reduced (divide by %d).\nK : Vortex86 changing CPU speed to ", bl    ; Print the current CPU speed modifier to the log
117
        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
118
.Vortex86CPUspeedMAX:
119
        DEBUGF  1, "MAX\n"              ; Now the CPU should be running at MAX speed (don't write the value to PCI port yet)
120
 
121
        cmp     [Vortex86CPUid], 3      ; MMX is available starting from CPU code 'MX' (id=3)
122
        jb      .skipVortex86MMX        ; No MMX support - skip MMX support status detection (for id=1,2)
123
        DEBUGF  1, "K : Vortex86 MMX support status: MMX is "                   ; Bits 5-6 in Host Control Register contain MMX status
124
        test    al, 100000b             ; On MMX-capable Vortex86 SoC, Bit5 = is MMX enabled? (1=Yes/0=No)
125
        jnz     .Vortex86MMXenabled     ; MMX is already enabled (Bit5=1)
126
        DEBUGF  1, "DISABLED - enabling it for this session\n"                  ; Print to the log that MMX is disabled
127
        or      al, 100000b             ; Enable MMX support (don't write the value to PCI port yet)
128
        jmp     .AfterMMXenabled
129
.Vortex86MMXenabled:
130
        DEBUGF  1, "ENABLED\n"          ; Print to the log that MMX is enabled
131
.AfterMMXenabled:
132
        DEBUGF  1, "K : Vortex86 MMX report to CPUID: "                         ; Print to the log what CPUID command knowns about MMX support
133
        test    al, 1000000b            ; On MMX-capable Vortex86 SoC, Bit6 = report MMX support to CPUID? (1=Yes/0=No)
134
        jnz     .Vortex86MMXreported    ; MMX is already reported to CPUID (Bit6=1)
135
        DEBUGF  1, "OFF - turning it ON for this session\n"                     ; Print to the log that MMX will now be reported to CPUID
136
        or      al, 1000000b            ; Turn on MMX reporting to CPUID (don't write the value to PCI port yet)
137
        jmp     .skipVortex86MMX
138
.Vortex86MMXreported:
139
        DEBUGF  1, "ON\n"               ; Print to the log that MMX reporting to CPUID is enabled
140
 
141
.skipVortex86MMX:
142
        cmp     bh, al                  ; Check whether AL has changed before (if it did, we need to write it back to PCI port)
143
        jz      .Vortex86end            ; No change - no need to write to the port
144
        out     dx, al                  ; Write the changed data to PCI port
145
        DEBUGF  1, "K : Vortex86 Host Control Register (A3h~A0h) new value is 0x%x\n",eax
4265 Serge 146
        jmp     .Vortex86end
4423 Serge 147
 
148
.Vortex86PCIreg:                        ; Procedure receives input register value in EAX, and returns the output value also in EAX
149
        mov     dx, 0xcf8               ; CF8h = Vortex86 PCI Configuration Address port
150
        out     dx, eax                 ; Send request to PCI address port to retrieve data from this address
151
        mov     dl, 0xfc                ; CFCh = Vortex86 PCI Configuration Data port
152
        in      eax, dx                 ; Read data from PCI data port
153
        ret
4265 Serge 154
 
4423 Serge 155
.nullPCIoutput:                         ; Emulators and non-Vortex86 CPU computers will usually return \0 in this register
156
        DEBUGF  1, "0 (NULL)\n"
4265 Serge 157
 
158
.Vortex86end: