summaryrefslogtreecommitdiff
path: root/cpu/amd/geode_lx/gplvsa_ii/sysmgr/port92.asm
blob: 0fb9d746adb78d12e098b719dafcaae7917afa00 (plain)
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