1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
|
;
; Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
;
; This library is free software; you can redistribute it and/or modify
; it under the terms of the GNU Lesser General Public License as
; published by the Free Software Foundation; either version 2.1 of the
; License, or (at your option) any later version.
;
; This code is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
; Lesser General Public License for more details.
;
; You should have received a copy of the GNU Lesser General
; Public License along with this library; if not, write to the
; Free Software Foundation, Inc., 59 Temple Place, Suite 330,
; Boston, MA 02111-1307 USA
;
;*******************************************************************************
;* Port 92h routines
;*******************************************************************************
include SYSMGR.INC
include VSA2.INC
include GX2.INC
include CHIPSET.INC
include CS5536.INC
include ISA.INC
include PCI.INC
include MDD.INC
include HCE.INC
include SMIMAC.MAC
.model tiny,c
.586p
.CODE
externdef VSA_Exit: proc
externdef MDD_Base: dword
externdef FooGlue: dword
externdef OHCI1_Smi: dword
externdef OHCI2_Smi: dword
externdef Nested_Flag: dword
externdef Saved_EAX: dword
externdef Saved_EBX: dword
externdef Saved_ECX: dword
externdef Saved_EDX: dword
externdef Saved_ESI: dword
externdef Saved_EDI: dword
externdef Saved_EBP: dword
externdef Saved_ESP: dword
externdef IDT_Base: dword
externdef IDT_Limit: dword
externdef IDT_Selector: dword
externdef SMI_Sources: dword
externdef SMM_Header: SmiHeader
externdef Saved_SS: Descriptor
externdef Data_Descriptor: Descriptor
externdef HardwareInfo: Hardware
;***********************************************************************
;
; A20_Sync - synchronize port 92h and virtual A20 pin
;
;***********************************************************************
A20_Sync proc uses si edi
; Determine if it is a nested access to port 92h
btr word ptr [Nested_Flag], SMI_SRC_A20_INDEX
jc short Get_A20_Data
rsdc gs, cs:[Data_Descriptor]
Get_A20_Data:
ASSUME SI: ptr SmiHeader
mov si, OFFSET VSM_Header.SysStuff.State
mov bl, byte ptr gs:[si].write_data ; Get I/O data
mov si, gs:[si].IO_addr ; Get I/O address
ASSUME SI:NOTHING
; Set A20M in FooGlue appropriately
mov ecx, [FooGlue]
add cx, FG_A20M
rdmsr
and al, NOT A20M ; A20M = 0
and bl, 02h ; Check A20M setting
jnz short Set_A20
or al, A20M ; Force A20 low
Set_A20:
wrmsr
cmp si, 0092h ; If port 92h, no update necessary
je short SyncHceControl
cmp si, KYBD_DATA ; If not 8042 data port, ignore
jne Return
; Sync Port 92h to keyboard controller
mov ecx, [MDD_Base] ; Disable Port 92h trapping
mov cx, MBD_MSR_SMI
rdmsr
push ax
and al, NOT A20_P_EN
wrmsr
mov al, bl ; Update Port 92h A20 state
out 92h, al
pop ax ; Restore Port 92h trapping
wrmsr
; Synchronize HceControl[A20State] with port 92h
SyncHceControl:
mov ecx, [OHCI1_Smi] ; Read OHCI1 h/w BAR0
test ecx, 0FFF00000h
jnz short Get_HC_Base
mov ecx, [OHCI2_Smi] ; Use OHCI2 if OHCI1 not used
test ecx, 0FFF00000h
jz Return
Get_HC_Base:
mov cx, 1000h + BAR0/4 ; 5536 Embedded PCI MSR
cmp [HardwareInfo].Chipset_ID, DEVICE_ID_5536
je short ReadBAR
mov cx, USBMSROHCB ; 5536 OHCI MSR
ReadBAR:
rdmsr
mov bh, 0 ; Clear MSR restore flag
or eax, eax ; Is BAR initialized ?
jnz short SyncA20State
mov bh, 1 ; Set MSR restore flag
push eax ; Save current OHCI MSR
push edx
push ecx
; OHCI BAR is not initialized or OHCI header is hidden.
; Temporarily map the OHCI register set just above VSA
; This range has been declared as OS-reserved in INT 15h E820h
mov ecx, MSR_RCONF_SMM
rdmsr
lea edi, [edx+1000h]
pop ecx
push ecx
mov edx, 00000000Eh
mov eax, edi
wrmsr
mov ecx, [MDD_Base]
mov cx, MSR_LBAR_KEL1
rdmsr
push eax ; Save current KEL LBAR
push edx
push ecx
mov eax, edi
mov edx, 0FFFFF001h
wrmsr
; Synchronize HceControl.A20State
SyncA20State:
or ax, OFFSET (HCOR Ptr ds:[0]).HceControl
mov dx, fs:[eax]
cmp dx, 0FFFFh ; Is Memory Space enabled ?
je short Exit
CLEAR_A20 equ (A20_STATE OR IRQ1_ACTIVE OR IRQ12_ACTIVE)
; SWAPSiF for SiBZ 3509/3571: KEL SMIs are level instead of edge-triggered
; Manifests itself as PBZ 3878: PS/2 keyboard hangs after running PCIDIAG
test dx, (IRQ1_ACTIVE OR IRQ12_ACTIVE)
jz short NoIRQ
or [SMI_Sources], SMI_SRC_KEL ; Fake another KEL SMI
NoIRQ:
and dx, NOT CLEAR_A20 ; Clear A20State
test bl, 02h
jz Update_HceControl
or dx, A20_STATE ; Set A20State
Update_HceControl:
mov fs:[eax], dx
Exit:
or bh, bh ; Do OHCI MSRs need to be restored?
je short Return
pop ecx ; Restore KEL LBAR
pop edx
pop eax
wrmsr
pop ecx ; Restore OHCI MSR
pop edx
pop eax
wrmsr
Return:
ret
A20_Sync endp
;***********************************************************************
; Sets the top-level RSM state to the reset state:
; 1) Real-mode IDT
; 2) Real-mode descriptors; segment regisers = 0000
; 3) CS:EIP = F000:FFF0
; 4) CS base = FFFF0000
; 5) CS limit = 64K
; 6) DX = CPU ID
;***********************************************************************
set_reset_state proc uses si
; Check if user code is doing a 286-style shutdown
in al, CMOS_INDEX ; Preserve CMOS index
mov ah, al
mov al, 0Fh
out CMOS_INDEX, al
in al, CMOS_DATA
xchg al, ah
out CMOS_INDEX, al ; Restore CMOS index
cmp ah, 09H
je UserShutdown
cmp ah, 05H
je UserShutdown
cmp ah, 0AH
je UserShutdown
cmp ah, 0FFH ; JMP if no CMOS present
je UserShutdown
CACHE_LINE_SIZE equ 32
; If cache is disabled, there is no way to guarantee that
; the entire code sequence from DisableCKE to Pre_Fetch
; will be fetched before CKE is disabled. It was decided
; we'd rather see the original POST 0xBF hang rather than
; a hang in SMM.
mov ebp, [MDD_Base] ; Prepare reset MSR
mov bp, MSR_SOFT_RESET
mov eax, CR0 ; Is cache disabled ?
test eax, 40000000h
jnz Reset
lea si, [DisableCKE] ; Move code to start of a cache line
mov di, si
and di, NOT (CACHE_LINE_SIZE-1)
mov bx, di ; Remember where we moved it to
cld
@@: lodsd
mov [di], eax
add di, 4
cmp si, OFFSET Pre_Fetch
jb @b
mov ecx, 2000001Dh ; Memory controller
rdmsr
or ah, 3 ; Set CKE Mask = 11b
jmp Pre_Fetch
; Bug #118.226 - Some DIMMs hang at POST 0xBF on a reboot
;
; Need to de-assert CKE off before command signals are tri-stated.
; There can be no memory accesses after the following WRMSR.
; If cache is disabled, there is no way to satisfy this condition,
; so some DIMMs with cache disabled is not supported with
; respect to resets.
db CACHE_LINE_SIZE dup (90h)
DisableCKE:
wrmsr
; Reset the CPU via MDD MSR_SOFT_RESET
Reset: mov ecx, ebp
mov al, 1
wrmsr
jmp $
Pre_Fetch:
; Prefetch 4 cache lines of NOPs so there won't be any
; prefetching to memory after the MC MSR is written.
db 4*CACHE_LINE_SIZE dup (90h) ; 4 cache lines
jmp bx
UserShutdown:
mov ecx, [FooGlue] ; Disable A20 mask
add cx, FG_A20M
rdmsr
and al, NOT A20M ; A20M = 0
wrmsr
; Disable the cache & flush it
mov eax, CR0
or eax, 60000000h
mov CR0, eax
wbinvd
; Set real-mode IDT
mov [IDT_Limit], 0FFFFh ; Limit
mov [IDT_Base], 00000000h ; Base
mov [IDT_Selector], 00920000h ; Selector & Attributes
; INIT is broken on LX 2.x and 3.0
cmp [HardwareInfo].CPU_ID, DEVICE_ID_LX
jne short Set_INIT
mov ax, [HardwareInfo].CPU_Revision
cmp al, 30h ; Is it 3.0?
jae short FakeInit
and al, 0F0h ; Is it 2.x?
cmp al, 20h
je short FakeInit
call VSA_Exit
; Reset via INIT MSR
Set_INIT:
mov ecx, [FooGlue] ; Reset the CPU
add cx, FG_INIT
xor eax, eax
wrmsr
mov al, INIT
wrmsr
; Fake an INIT by setting up initial CPU state
FakeInit:
lea si, [Saved_SS] ; Set descriptors to 64K real-mode
mov cx, 5 ; # descriptors to fill
mov eax, 0000FFFFh ; limit_15_0 & base_15_0
DescrLoop:
mov [si+0], eax ; limit_15_0 & base_15_0
mov dword ptr [si+4], 00009200h ; base_23_16, attr, limit_19_16 & base_31_24
mov word ptr [si+8], 0000h ; selector
add si, sizeof (Descriptor) ; Advance ptr to next descriptor
loop DescrLoop
; Set top-level SMM header to reset state
mov bx, OFFSET SMM_Header
ASSUME BX: PTR SmiHeader
mov [bx]._CS.limit, eax
mov [bx]._CS.base, 0FFFF0000h
mov [bx]._CS.selector, 0F000h
mov [bx]._CS.attr, 92h
mov [bx].Next_EIP, 0000FFF0h
mov [bx].r_CR0, 60000010h ; Real-mode; cache disabled
mov [bx].r_DR7, 00000400h
mov [bx].EFLAGS, 00000002h
mov [bx].SMI_Flags, 8001h ; CS is R/W
mov [bx].SS_Flags, DATA_ATTR
; Initialize general purpose register
mov [Saved_EDX], 00000540h ; CPU ID
xor eax, eax
mov [Saved_EAX], eax
mov [Saved_EBX], eax
mov [Saved_ECX], eax
mov [Saved_EDI], eax
mov [Saved_ESI], eax
mov [Saved_EBP], eax
mov [Saved_ESP], eax
ret
set_reset_state endp
end
|