Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
4261 yogev_ezra 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
5363 yogev_ezra 3
;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;;
4261 yogev_ezra 4
;; Distributed under terms of the GNU General Public License    ;;
5
;;                                                              ;;
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7
 
4294 yogev_ezra 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
11
 
4261 yogev_ezra 12
$Revision: 7122 $
13
 
14
VORTEX86DEBUG = 0                       ; For testing in emulators and in non-Vortex86 CPU computers, set this to 1
7122 dunkaist 15
VORTEX86DEBUGVALUE = 'DMP5'             ; FAKE port output = used for testing
4310 yogev_ezra 16
NORTH_BRIDGE = 0x80000000               ; Base address of Vortex86 PCI North Bridge
17
SOUTH_BRIDGE = 0x80003800               ; Base address of Vortex86 PCI South Bridge
4261 yogev_ezra 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
4294 yogev_ezra 35
        db      0x33, 'MX '     ; id=3  MMX is available starting from CPU code 'MX' (id=3)
4261 yogev_ezra 36
        db      0x34, 'DX2'     ; id=4
37
        db      0x35, 'MX+'     ; id=5
4294 yogev_ezra 38
        db      0x37, 'EX '     ; id=7
39
Vortex86SoCnum = ($ - Vortex86SoClist) / 4      ; Calculate the total number of known Vortex86 CPUs
4261 yogev_ezra 40
endg
41
 
4272 yogev_ezra 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
4294 yogev_ezra 47
end if
4272 yogev_ezra 48
 
4310 yogev_ezra 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)
4261 yogev_ezra 51
 
4272 yogev_ezra 52
if VORTEX86DEBUG                        ; When in debug mode, pretend that we received port output equal to "VORTEX86DEBUGVALUE"
4261 yogev_ezra 53
        mov     eax, VORTEX86DEBUGVALUE
4294 yogev_ezra 54
end if
4261 yogev_ezra 55
 
4294 yogev_ezra 56
        DEBUGF  1, "K : Vortex86 SoC type register (93H~90H) returned 0x"
4289 yogev_ezra 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)
4294 yogev_ezra 66
        jnz     .notVortex86            ; If it's not Vortex86 - go say so and exit
4289 yogev_ezra 67
 
4294 yogev_ezra 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
 
4261 yogev_ezra 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
@@:
4289 yogev_ezra 75
        inc     ecx                     ; Increment our counter
4261 yogev_ezra 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
4289 yogev_ezra 81
 
4261 yogev_ezra 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
 
4294 yogev_ezra 85
        DEBUGF  1, "%s (id=%d)\n", Vortex86SoCname, [Vortex86CPUid]:1           ; Say what we have found (CPU name and id)
86
        jmp     .Vortex86
87
 
4289 yogev_ezra 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"
4261 yogev_ezra 90
        jmp     .Vortex86end
4289 yogev_ezra 91
 
4294 yogev_ezra 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:
4310 yogev_ezra 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
107
 
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)
4294 yogev_ezra 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)
4310 yogev_ezra 115
        inc     ebx                     ; The actual value is 1 less than 'Divide by' setting (value '001' means 'Divide by 2', etc.)
4294 yogev_ezra 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
4261 yogev_ezra 146
        jmp     .Vortex86end
147
 
4294 yogev_ezra 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
154
 
4289 yogev_ezra 155
.nullPCIoutput:                         ; Emulators and non-Vortex86 CPU computers will usually return \0 in this register
156
        DEBUGF  1, "0 (NULL)\n"
157
 
7122 dunkaist 158
.Vortex86end: