summaryrefslogtreecommitdiff
path: root/Chipset/eM/Ahci/AHCIACC.ASM
blob: 1f93536a0b5bee55d935d65940cd3e0b7f5d2e35 (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
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181

        TITLE   AHCIACC.ASM - AHCI Register/Memory Acccess Routines

;****************************************************************************
;****************************************************************************
;**                                                                        **
;**             (C)Copyright 1985-2014, American Megatrends, Inc.          **
;**                                                                        **
;**                          All Rights Reserved.                          **
;**                                                                        **
;**                 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093      **
;**                                                                        **
;**                          Phone (770)-246-8600                          **
;**                                                                        **
;****************************************************************************
;****************************************************************************

;****************************************************************************
; $Header: /Alaska/SOURCE/Modules/AHCI/INT13/CSP/AHCIACC.ASM 14    12/08/14 5:58a Anbuprakashp $
;
; $Revision: 14 $
;
; $Date: 12/08/14 5:58a $
;****************************************************************************
; Revision History
; ----------------
; $Log: /Alaska/SOURCE/Modules/AHCI/INT13/CSP/AHCIACC.ASM $
; 
; 14    12/08/14 5:58a Anbuprakashp
; [TAG]  		EIP192297
; [Category]  	Improvement
; [Description]  	Replacing SmmGetMemoryType usage in AHCI driver with
; AmiBufferValidationLib
; [Files]  		AhciInt13Smm.c, AhciInt13Smm.mak, AHCIACC.ASM
; 
; 13    11/24/14 11:54p Kapilporwal
; [TAG]  		EIP191939
; [Category]  	Improvement
; [Description]  	Issue about BIG_REAL_MODE_MMIO_ACCESS of AHCI module
; [Files]  		AI13.bin
; AHCIACC.ASM
; AhciInt13Dxe.c
; AhciInt13Dxe.dxs
; AhciInt13Smm.c
; AhciInt13Smm.cif
; AhciInt13Smm.dxs
; AhciInt13Smm.h
; AhciInt13Smm.mak
; AhciInt13Smm.sdl
; AInt13.c
; Aint13.cif
; AInt13.h
; AhciSmm.c
; AhciSmm.h
; AhciSmmProtocol.h
; 
; 12    7/01/14 2:23a Nagadineshk
; [TAG]  		EIP172162 
; [Category]  	Bug Fix
; [Severity]  	Important
; [Symptom]  	Can't install legacy windows if achiacc.obj is not first
; one of CSM_OEM16_OBJS elink
; [RootCause]  	Wrong offset of Newly Hooked Interrupt(CPU Exception
; Interrupt) address loaded in Interrupt vector table.
; [Solution]  	Stored Correct Offset value in IVT
; [Files]  		AHCIACC.ASM
; 
; 11    6/20/14 6:54a Nimishsv
; Recheck-in
; 
; 10    12/17/13 7:06a Nimishsv
; [TAG]  		EIP131322 
; [Category]  	Improvement
; [Description] Improve S4 resume time with PCIE SSD
; under Win7, reported that if enable AHCIMMIOSMM_SUPPORT,
; and then S4 resume time is very long(about 50s) with win 7.
; (Add support for accessing MMIO region using BIG real mode)
; [Files]  		AhciMmioSmm.sdl, AHCIACC.asm
; 
; 9     8/02/12 8:14a Deepthins
; [TAG]  		EIP93480
; [Category]  	Bug Fix
; [Symptom]  	AHCI legacy support module is corrupting the memory.
; [RootCause]  	AHCI legacy support module is corrupting the memory as it
; was using wrong offset for storing the base address.
; [Solution]  	Properly calculating offset for storing the base address.
; [Files]  		AINT13.EQU, AInt13.c, AInt13.h and AHCIACC.ASM
; 
; 8     1/13/12 12:20a Deepthins
; [TAG]  		EIP78099
; [Category]  	Improvement
; [Description]  	Handle multiple AHCI controller in legacy.
; [Files]  		Aint13.sdl , AInt13.c , AInt13.h , AHCIACC.ASM , AHCI.EQU ,
; AINT13.bin (AHCIACC.ASM , AINT13.EQU)
; 
; 7     2/10/11 10:52a Rameshr
; [TAG]  		EIP53704
; [Category]  	Improvement
; [Description]  	AMI headers update for Alaska Ahci Driver
; [Files]  		AHCIACC.ASM
; HACCESS.EQU
; AHCI.EQU
; AINT13.EQU
; AInt13Csp.c
; 
; 6     6/21/10 5:34a Rameshr
; AHCI Legacy booting through MMIO reg.
; EIP 38444
; 
; 5     5/28/08 9:43a Rameshraju
; Updated the AMI Address.
; 
; 4     3/28/08 10:03a Olegi
; 
; 3     3/27/08 5:33p Olegi
; 
; 2     19/12/07 4:28p Anandakrishnanl
; Modified the relative offsets to be absolute.
; 
; 1     12/07/07 11:17a Olegi
;
;****************************************************************************

;----------------------------------------------------------------------------
;       INCLUDE FILES
;----------------------------------------------------------------------------
        include ahci.equ
        include haccess.equ
        include aint13.equ
        include token.equ

	FLAT_MODE_INDEX equ 08h
	REAL_MODE_INDEX equ 10h
;----------------------------------------------------------------------------
;       EXTERNS USED
;----------------------------------------------------------------------------
.586p
OEM16_CSEG SEGMENT PARA PUBLIC 'CODE' USE16
        ASSUME cs:OEM16_CSEG, ds:OEM16_CSEG
;-------------------------------------------------------------------------
        PUBLIC AhciApiModuleStart
AhciApiModuleStart LABEL BYTE
        jmp     SHORT AhciCsm16Api
        dw      AhciDataStart - AhciApiModuleStart 


;----------------------------------------------------------------------------
; IMPORTANT: Do not put any OEM/CHIPSET code above this, the above code and
;            and data are at fixed locations.
;----------------------------------------------------------------------------

;-------------------------------------------------------------------------
;                       AHCI_CSM16_API_Start
;----------------------------------------------------------------------------
; This routine is implementation of the CSM16 API #7.
; Input:        CX      80h   - ReadRegisterDword call
;                       00h   - WriteRegisterDword call
;                       01h   - WaitForFisRecRun call
;               For read/write functions:
;                   SS:SP+3Eh (originally ESI)  HBA Base Address
;                   SS:SP+42h (originally EBX)  Port#, Register Offset
;                       Bit31-16 = Port# (0-based)
;                                  FFFF for Generic Host Control Register
;                       Bit15-0  = Register offset
;                   SS:SP+46h  (originally EAX) Data to be written
;               For WaitForFisRecRun function:
;                   No input
; Output:       NC      Successful
;                       EAX     Data read
;               CY      Error
; Register Usage: Do not destroy any register except EAX
;
;----------------------------------------------------------------------------
;
AhciCsm16Api  PROC FAR PUBLIC
; Adjust current IP so that the data offsets are valid
        call    $+3     ; Push curent IP
        pop     bx		; Get current IP in BX
        shr     bx, 4
        mov     ax, cs      ; Always x000h
        add     ax, bx      ; New CS
        push    ax
        push    newOffset-AhciApiModuleStart
        retf            ; Execute from new CS:IP

newOffset:
        push    bp
        mov     bp, sp
        mov     eax, ss:[bp+48h]    ; Data to be written (ignored for Read function)
        mov     ebx, ss:[bp+44h]    ; Port#
        mov     esi, ss:[bp+40h]    ; HBA Base Address

        cmp     cx, 0
        jz      aca_WriteCall
        cmp     cx, 80h
        jnz     aca_WaitForFisRecRun
        call    ReadRegisterDword
        jmp     SHORT aca_Exit
aca_WaitForFisRecRun:
        call    WaitForFisRecRun
        jmp     SHORT aca_Exit
aca_WriteCall:
        call    WriteRegisterDword

aca_Exit:
        pop     bp

; Adjust sp as if we returned to csm16_func_ret
        add     sp, 4   ; cs:ip of F000:csm16_func_ret

; Save EAX, restore it after popad
        push    eax
        pop     ds
        pop     gs
;csm16_func_ret:
        popad
        push    gs
        push    ds
        pop     eax

        pop     gs
        pop     fs
        pop     es
        pop     ds

;csm16_exit:
        popf
        pop     ds
        pop     si
    
        add     sp, 2   ; Do not "pop ax", preserving return code

; Prepare for FAR return - fetch the CS and patch the segment for RETF
        mov     cx, WORD PTR ss:[bp+1ah]
        mov     WORD PTR ss:[bp+06h], cx
; Restore CX
        mov    cx, WORD PTR ss:[bp+18h] 
        mov    dx, WORD PTR ss:[bp+16h] ;Restore Dx

        pop     bp
        add     sp, 4
        clc
        retf    18

AhciCsm16Api  ENDP

;
;-------------------------------------------------------------------------
;                       ReadRegisterDword
;----------------------------------------------------------------------------
; This routine reads the register.
; Input:        ESI     HBA Base Address
;               EBX     Port#, Register Offset
;                       Bit31-16 = Port# (0-based)
;                                  FFFF for Generic Host Control Register
;                       Bit15-0  = Register offset
; Output:       NC      Successful
;                       EAX     Data read
;               CY      Error
; Register Usage: Do not destroy any register except EAX
;
;----------------------------------------------------------------------------
;
ReadRegisterDword_FAR   PROC    FAR     PUBLIC
        call    ReadRegisterDword       ; EAX = data read if read
        ret
ReadRegisterDword_FAR   ENDP

ReadRegisterDword       PROC    NEAR    PUBLIC
        push    esi
        call    CalculateRegisterOffset ; ESI = register offset from base

        push    dx                      ; Dx has the controller number
        cli
        push    bx                      ; Save bx value in stack
        push    ax                      ; Save ax value in stack
        mov     ax, 0
        mov     al, dl                  ; Move the controller no into al
        mov     bl, 8
        mul     bl                      ; Multiply it with 8 as AHCI_ACCESS\
                                        ; structure size is 8
        mov     bx, ax                  ; Move the offset into bx
        pop     ax                      ; Restore ax
IF (MKF_AHCI_INT13_SMM_SUPPORT)
        push    ebx
        push    ecx        
        mov     ebx, dword ptr cs:[AhciDataStart - AhciApiModuleStart +4+bx] ;ebx=Data
        add     esi,ebx
IF (MKF_BIG_REAL_MODE_MMIO_ACCESS)	
    	call	ReadDWORD
ELSE
        mov     cx,1                    ;Read Function
        call    AhciGenerateSwSMI
        cmp     ecx, 0                  ; if ECX == 0, MMIO read is Success
        jz      Read_Success
        stc
        jmp     Read_Return
Read_Success:
        clc
Read_Return:
ENDIF
        pop     ecx
        pop     ebx
        jmp     Read_done
ENDIF
        mov     dx, cs:[AhciDataStart - AhciApiModuleStart +bx]              ; DX = Index Port
        push    eax
        mov     eax, esi                ; EAX = register address
        out     dx, eax                 ; Write Address
        pop     eax

        mov     dx, cs:[AhciDataStart - AhciApiModuleStart +2+bx]              ; DX = Data Port
        in      eax, dx                 ; EAX = adat

        clc                             ; NC, Successful
Read_done:
        pop     bx
        pop     dx

        pop     esi
        ret
ReadRegisterDword       ENDP
;
;----------------------------------------------------------------------------
;                       WriteRegisterDword
;----------------------------------------------------------------------------
; This routine writes the register.
; Input:        ESI     HBA Base Address
;               EBX     Port#, Register Offset
;                       Bit31-16 = Port# (0-based)
;                                  FFFF for Generic Host Control Register
;                       Bit15-0  = Register offset
;               EAX     Data to be written
; Output:       NC      Successful
;               CY      Error
; Register Usage: Do not destroy any register
;
;----------------------------------------------------------------------------
;
WriteRegisterDword_FAR  PROC    FAR     PUBLIC
        call    WriteRegisterDword
        ret
WriteRegisterDword_FAR  ENDP

WriteRegisterDword      PROC    NEAR    PUBLIC
        push    esi
        call    CalculateRegisterOffset ; ESI = register offset from base

        push    dx                      ; Dx has the controller number
        cli
        push    bx                      ; Save bx value in stack
        push    ax                      ; Save ax value in stack
        mov     ax, 0
        mov     al, dl                  ; Move the controller no into al
        mov     bl, 8
        mul     bl                      ; Multiply it with 8 as AHCI_ACCESS\
                                        ; structure size is 8
        mov     bx, ax                  ; Move the offset into bx
        pop     ax                      ; Restore ax

IF (MKF_AHCI_INT13_SMM_SUPPORT)
        push    ebx
        push    ecx
        mov     ebx, dword ptr cs:[AhciDataStart - AhciApiModuleStart +4+bx]
        add     esi,ebx
IF (MKF_BIG_REAL_MODE_MMIO_ACCESS)	
    	call	WriteDWORD
ELSE
        mov     ebx,eax                 ;Write Value
        mov     cx,2                    ;Write Function
        call    AhciGenerateSwSMI
        cmp     ecx, 0                  ; if ECX == 0, MMIO write is Success
        jz      Write_Success
        stc
        jmp     Write_Return
Write_Success:
        clc
Write_Return:
ENDIF
        pop     ecx
        pop     ebx
        jmp     Write_done
ENDIF
        mov     dx, cs:[AhciDataStart - AhciApiModuleStart +bx]              ; DX = Index Port
        push    eax
        mov     eax, esi                ; EAX = register address
        out     dx, eax                 ; Write Address
        pop     eax

        mov     dx, cs:[AhciDataStart - AhciApiModuleStart +2+bx]              ; DX = Data Port
        out     dx, eax                 ; Write dword data
        clc                             ; NC, Successful
Write_done:
        pop     bx
        pop     dx

        pop     esi
        ret
WriteRegisterDword      ENDP
;
;----------------------------------------------------------------------------
;                       CalculateRegisterOffset
;----------------------------------------------------------------------------
; This routine calculates the register offset from HBA Base.
; Input:        EBX     Port#, Register Offset within Port
;                       Bit31-16 = Port# (0-based)
;                                  FFFF for Generic Host Control Register
;                       Bit15-0  = Register offset
; Output:       ESI     Register Offset from HBA Base
; Register Usage: Do not destroy any register except ESI
;
;----------------------------------------------------------------------------
;
CalculateRegisterOffset PROC    NEAR    PRIVATE
        push    cx
        push    ebx
        mov     cx, bx                  ; CX = register offset
        shr     ebx, 16                 ; BX = Port# (0-based)
        inc     bx                      ; Port# valid?
        jz      short cro_00            ; No
        dec     bx                      ; BX = Port# (0-based)
        shl     bx, PORT_REGISTER_SET_SIZE_N
        add     bx, PORT_REGISTER_START
cro_00:
        add     bx, cx                  ; BX = Port register offset from HBA base address
        movzx   esi, bx                 ; ESI = Port register offset from HBA base address
        pop     ebx
        pop     cx
        ret
CalculateRegisterOffset ENDP

;
;----------------------------------------------------------------------------
;                       WaitForFisRecRun
;----------------------------------------------------------------------------
; This routine executes HBA wait for FIS rec run code. If not
; implemented (just ret), AHCI INT13 code will execute the default routine.
; Implement this routine for different OEM/Chipset vendor and return 0 in AL
; to override the default routine execution.
;
; Output:       AH     0 if implemented
;
;----------------------------------------------------------------------------
;
WaitForFisRecRun    PROC NEAR PUBLIC
        ret
WaitForFisRecRun    ENDP

;<AMI_PHDR_START>
;----------------------------------------------------------------------------
;
; Procedure:    AhciGenerateSwSMI 
;
; Description:  Generate the Sw SMI to read the MMIO space.
;               if the system is in big real mode, read/write the MMIO space without 
;               SwSMI  
;
; Input:        Cx = 1 - Read MMIO
;               Cx=  2 - Write MMIO 
;               Eax= Value to write in MMIO for write MMIO 
;                    
; Output:       Eax- for Read MMIO 
;
; Modified:     Ds
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>
IF (MKF_AHCI_INT13_SMM_SUPPORT)
AhciGenerateSwSMI    PROC NEAR PUBLIC
        call    Check_Big_Real_mode
        jc      NotBigReadMode
        push    es
        push    0
        pop     es

        cmp     cx,1
        je      ReadMmio
        mov     dword ptr es:[esi],eax  ;Write MMIO  
        pop     es
        ret
ReadMmio:
        mov     eax,dword ptr es:[esi]  ;Read MMIO
        pop     es
        ret
NotBigReadMode:

        mov     dx,MKF_SW_SMI_IO_ADDRESS     
        mov     al,MKF_AHCI_INT13_SMM_SWSMI_VALUE
        out     dx,al                   ;Generate Sw SMI to Read/Write MMIO
        jmp     $+2
        ret
AhciGenerateSwSMI    ENDP

;-------------------------------------------------------------------------
;			ReadDWORD
;-------------------------------------------------------------------------
; This routine reads DWORD from MMIO.
; Input:	ESI	HBA Base Address
;
; Output:	NC	Successful
;			EAX	Data read
;			CY	Error
; Register Usage: Do not destroy any register except EAX
;
;-------------------------------------------------------------------------
ReadDWORD	PROC	NEAR	PUBLIC

	push	ds

	push	0
	pop	ds

	push	esi

; Save original values of registers in stack	
	push	ebx
	push	es
	push	di
	
; Save a dword from 5000h
	mov	bx, 5000h
	mov	es, bx
	mov	di, 00h
	mov	ebx, dword ptr es:[di]

	push	ebx

	mov	byte ptr es:[di], 00h
; Switching to Big Real Mode
	call	Switch_Big_Real_Mode
	
; Reading DWORD from Hba_base_address and store in EAX
	mov	eax, dword ptr ds:[esi]

	push	eax
	movzx	eax, byte ptr es:[di]
	and	eax, 01h
	jz	rdw_done
; Switch back from Big Real mode
	call	Switch_Original_Mode

rdw_done:
	pop	eax

	push	eax
	movzx	eax, byte ptr es:[di]
	and	eax, 10b
	jz	org_g20
	call	DisblGateA20
org_g20:
	pop	eax

	pop	ebx
; Restore the original values stored in stack
	mov	dword ptr es:[di], ebx

	pop	di
	pop	es
	pop	ebx

	pop	esi

	pop	ds
	clc

	ret
ReadDWORD	ENDP

;-------------------------------------------------------------------------
;			WriteDWORD
;-------------------------------------------------------------------------
; This routine writes DWORD in MMIO space.
; Input:	EAX	Data to be written
;
; Output:	ESI	HBA Base Address
;			NC	Successful
;			CY	Error
;
; Register Usage: Do not destroy any register except EAX
;
;-------------------------------------------------------------------------
WriteDWORD	PROC	NEAR	PUBLIC
	push	ds

	push	0
	pop	ds

	push	esi

; Save original values of registers in stack
	push	ebx
	push	es
	push	di
	
; Save a dword from 5000h
	mov	bx, 5000h
	mov	es, bx
	mov	di, 00h
	mov	ebx, dword ptr es:[di]

	push	ebx

	mov	byte ptr es:[di], 00h
; Switching to Big Real Mode
	call	Switch_Big_Real_Mode
	
; Writing DWORD stored in EAX into Hba_base_address
	mov	dword ptr ds:[esi],eax

	push	eax
	movzx	eax, byte ptr es:[di]
	and	eax, 01h
	jz	wdw_done
	
; Switch back from Big Real mode
	call	Switch_Original_Mode
	
wdw_done:
	pop	eax

	push	eax
	movzx	eax, byte ptr es:[di]
	and	eax, 10b
	jz	org_g201
	call	DisblGateA20
org_g201:
	pop	eax
	pop	ebx

; Restore the original values stored in stack
	mov	dword ptr es:[di], ebx

	pop	di
	pop	es
	pop	ebx

	pop	esi

	pop	ds
	clc

	ret
WriteDWORD	ENDP

;----------------------------------------------------------------------------
;<AMI_PHDR_START>
;----------------------------------------------------------------------------
;
; Procedure:    Switch_Big_Real_Mode
;
; Description:  Switch to Big real Mode. 
;
; Input:        None 
;                    
; Output:       
;
; Modified:     DS, ES
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>
;----------------------------------------------------------------------------
Switch_Big_Real_Mode PROC NEAR PUBLIC

	push	di
	call    Check_Big_Real_mode
	jnc     InBigRealMode
	mov	byte ptr es:[di], 01h

InBigRealMode:

	mov	di, FLAT_MODE_INDEX                          ;Index for flat mode
	call	GotoProtectedMode

	pop	di
    ret

Switch_Big_Real_Mode ENDP

;----------------------------------------------------------------------------
;<AMI_PHDR_START>
;----------------------------------------------------------------------------
;
; Procedure:    Switch_Original_Mode
;
; Description:  Switch to Original Mode. 
;
; Input:        None 
;                    
; Output:       
;
; Modified:     DS, ES
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>
;----------------------------------------------------------------------------
Switch_Original_Mode PROC NEAR PUBLIC

	push	di
	mov	di,	REAL_MODE_INDEX			;Real mode index
	call	GotoProtectedMode
	pop	di

    ret

Switch_Original_Mode ENDP

;<AMI_PHDR_START>
;----------------------------------------------------------------------------
;
; Procedure:	GotoProtectedMode
;
; Description:	This function jumps to protected mode for 4GB limit access
;
; Input:	None
;
; Output:	None
;
; Modified:	None
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>

GotoProtectedMode PROC NEAR PUBLIC
	push	es
	pusha
	cli				; Disable interrupts.
;  Check the GA20 status..
;  Compare 256bytes at 0:0 with FFFF:10
;  If match, GA20 is disabled else GA20 is enabled.
	push	di
	push	es
	push	ds
	push	0000h
	pop	ds			; DS = 0000.
	push	0FFFFh
	pop	es			; ES = FFFF.
	mov	cx, 100h / 4		; Number of Dwords in 256bytes.
	xor	si, si
	mov	di, 0010h
	repz	cmpsd
	pop	ds
	pop	es
	pop	di                  ;Descriptor table index in di 

	pushf				; Save GA20 status
					; ZR/NZ = disabled/enabled.
	jnz	short gtbrm_00		; GA20 is already enabled.
	
	push	di
	mov	di, 00h
	or	byte ptr es:[di], 10b
	pop	di
	call	EnblGateA20		; Enable GateA20.

gtbrm_00:
	call	go_big_mode		; Go to protected mode and comeback
					; to real mode.
	popf				; ZR/NZ = GA20 status.
	stc				; Routine went to big real mode.

gtbrm_01:
	popa
	pop	es
	ret				; Return to caller.
GotoProtectedMode ENDP

;<AMI_PHDR_START>
;----------------------------------------------------------------------------
;
; Procedure:	EnblGateA20
;
; Description:	This function enables GateA20
;
; Input:	None
;
; Output:	None
;
; Modified:	None
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>

EnblGateA20 PROC NEAR PUBLIC

	push	ax
	mov	al,02h
	out	92h, al

;  Check the GA20 status..
;  Compare 256bytes at 0:0 with FFFF:10
;  If match, GA20 is disabled else GA20 is enabled.
	push	di
	push	es
	push	ds
	push	0000h
	pop	ds			; DS = 0000.
	push	0FFFFh
	pop	es			; ES = FFFF.
	mov	cx, 100h / 4		; Number of Dwords in 256bytes.
	xor	si, si
	mov	di, 0010h
	repz	cmpsd
	pop	ds
	pop	es
	pop	di                  ;Descriptor table index in di 

	jnz	eg20_end

    mov	al, 0DFh		; Data for output port to enable A20.
	out	60h, al
	mov	al, 0D1h		
	out	64h, al

eg20_end:
	pop	ax

	ret
EnblGateA20 ENDP

;<AMI_PHDR_START>
;----------------------------------------------------------------------------
;
; Procedure:	go_big_mode
;
; Description:	This routine goes to protected mode, sets the DS, ES to the
;		given selector, comes back to real mode and sets DS, ES to 0000.
;
; Input:	DX	- Selector.
;
; Output:	Selector 00 can be used to access 4GB.
;
; Modified:	EAX.
;
; Referrals:	big_gdt.
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>

go_big_mode PROC NEAR PRIVATE

	jmp	Executable_code

;<AMI_SHDR_START>
;----------------------------------------------------------------------------
; Name:		big_gdt
;
; Type:		BYTE Array
;
; Description:	Global Descriptor Table to switch the system to/from FLAT Mode.
;		Since these routines will be called from non-shadowed system
;		ROM, the GDT must be on a QWORD boundary or else the bytes
;		will get CORRUPTED!
;
;----------------------------------------------------------------------------
;<AMI_SHDR_END>

ALIGN	8
big_gdt		LABEL	WORD
	db	8 dup (0)			;00 - Null descriptor	
	db	0FFh,0FFh,000h,000h,000h,093h,08Fh,000h	; 08h - DS descriptor for flat mode
big_gdt_end	LABEL	WORD

big_gdt_real	LABEL	WORD
	db	8 dup (0)			;00 - Null descriptor	
	db	0FFh,0FFh,000h,000h,000h,093h,000h,000h	; 08h - DS descriptor for real mode
big_gdt_real_end	LABEL	WORD

GDT_DESC	LABEL	BYTE
	dw	010h				; Length of GDT
	db	00,00h				; ptr to GDT
	db	05h,00h
GDT_DESC_END	LABEL	BYTE

Executable_code:
	
	push	ds
	push	es
	push	eax
	push	ebx
	push	ecx
	push	edx
	push	si
	push	di

; Changed for CSM - need to save SS, reload SS Limit to 64K selector and restore it
	push	bp
	mov	bp, ss

	mov	al, 8Dh			; Disable NMI
	out	70h, al
	
;;; Copy contents from 5000:00(16 bytes) into registers
	mov	ax, 5000h
	mov	es, ax
	mov	si, 00h
	mov	eax, dword ptr es:[si]
	add	si, 4
	mov	ebx, dword ptr es:[si]
	add	si, 4
	mov	ecx, dword ptr es:[si]
	add	si, 4
	mov	edx, dword ptr es:[si]
	push	eax
	push	ebx
	push	ecx
	push	edx

;;; Copy GDT to 5000h:00h 		
	mov	ax, cs
	mov	ds, ax
	cmp	di, 08h
	jne gbm_real
	mov	si, offset cs:big_gdt
	jmp gbm_flat
gbm_real:
	mov	si, offset cs:big_gdt_real
gbm_flat:
	mov	ax, 5000h
	mov	es, ax
	mov	di, 00h
	xor	cx, cx
	mov	cx, 08h 
	rep	movsw	

	lgdt	fword ptr cs:GDT_DESC
	mov	eax, cr0
	or	al, 01h
	mov	cr0, eax		; In protected mode.
	jmp	gbm_00			; Flush instruction queue - JMP (NEAR)
					; to next instruction.

gbm_00:
	mov	ax, 08h			; Selector
        mov     ds, ax                  ; DS = selector.
        mov     es, ax                  ; ES = selector.

	mov	eax, cr0		; Come back into real mode with DS,ES
	and	al, 0FEh
	mov	cr0, eax		
	jmp	gbm_01			; Flush instruction queue - JMP (NEAR)
					; to next instruction.
gbm_01:

	xor	ax, ax
	mov	ds, ax
	mov	es, ax

	pop	edx
	pop	ecx
	pop	ebx
;;; Restore contents of 5000:00h(16 bytes) from registers	
	mov	ax, 5000h
	mov	es, ax
	mov	si, 00h
	pop	eax
	mov	dword ptr es:[si], eax
	add	si, 4
	mov	dword ptr es:[si], ebx
	add	si, 4
	mov	dword ptr es:[si], ecx
	add	si, 4
	mov	dword ptr es:[si], edx

	pop	bp
	pop	di
	pop	si
	pop	edx
	pop	ecx
	pop	ebx
	pop	eax
	pop	es
	pop	ds
	ret
go_big_mode ENDP

;<AMI_PHDR_START>
;----------------------------------------------------------------------------
;
; Procedure:	DisblGateA20
;
; Description:	This function disables GateA20
;
; Input:	None
;
; Output:	None
;
; Modified:	None
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>

DisblGateA20 PROC NEAR PUBLIC

	push	ax
	mov	al,00h
	out	92h, al

;  Check the GA20 status..
;  Compare 256bytes at 0:0 with FFFF:10
;  If match, GA20 is disabled else GA20 is enabled.
	push	di
	push	es
	push	ds
	push	0000h
	pop	ds			; DS = 0000.
	push	0FFFFh
	pop	es			; ES = FFFF.
	mov	cx, 100h / 4		; Number of Dwords in 256bytes.
	xor	si, si
	mov	di, 0010h
	repz	cmpsd
	pop	ds
	pop	es
	pop	di                  ;Descriptor table index in di 

	jz	dg20_end

	mov	al, 0DDh		; Data for output port to disables A20.
	out	60h, al
	mov	al, 0D1h		
	out	64h, al

dg20_end:
	pop	ax

	ret

DisblGateA20 ENDP

;<AMI_PHDR_START>
;----------------------------------------------------------------------------
;
; Procedure:    Get_EBDA
;
; Description:  Get the EBDA Segment Address 
;
; Input:        None 
;                    
; Output:       DS: Ebda Segment 
;
; Modified:     Ds
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>
Get_EBDA PROC NEAR PUBLIC

    push    40h
    pop     ds
    mov     ds, ds:[0Eh]                ; DS - EBDA segment.
    ret

get_EBDA ENDP

;<AMI_PHDR_START>
;----------------------------------------------------------------------------
;
; Procedure:    Int0DHandler
;
; Description:  Exception 0D handler 
;
; Input:        None 
;                    
; Output:       Exception_flag Set
;
; Modified:     None
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>
Int0DHandler PROC NEAR PUBLIC
        push    ds
        call    Get_EBDA
        mov     byte ptr ds:[102h],1    ;Set the Flag in Ebda:102
        pop     ds
        pop     ax
        add     ax, 5                   ; Go to Next instruction that doesn't 
                                        ; cause Exception 
        push    ax
        iret
Int0DHandler  ENDP

;<AMI_PHDR_START>
;----------------------------------------------------------------------------
;
; Procedure:    Check_Big_Real_mode
;
; Description:  This function checks wheather system is in Big real mode
;
; Input:        None 
;                    
; Output:       Carry Set - Not in Big Real mode 
;               Carry Not Set- System is in Big Real mode                 
;
; Modified:     None
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>
Check_Big_Real_mode  PROC NEAR PUBLIC
        push    eax
        push    edi
        push    ebx
        push    es
        push    ds
        pushf
        cli

        call    Get_EBDA

        mov     byte ptr ds:[102h],0    ;EBDA:102

        push    0
        pop     es

        mov     eax, dword ptr es:[0Dh*4]
        push    eax
               
        push    cs                      ; Runtime segment
        push    offset cs:Int0DHandler-AhciApiModuleStart
        pop     eax
        mov     dword ptr es:[0Dh*4], eax


        mov     edi,0100000h
        mov     eax,dword ptr es:[edi]
        cmp     byte ptr ds:[102h],1    ;Check the exception
        je      Real_mode

        mov     edi,0
        mov     ebx,dword ptr es:[edi]
        cmp     eax,ebx
        je      Real_mode

                                        ;Read ,Write test for above 1Mb area
        mov     edi,0100000h
        mov     ebx,dword ptr es:[edi]
        mov     eax,055AA55AAh
        mov     dword ptr es:[edi],eax
        mov     eax,dword ptr es:[edi]
        mov     dword ptr es:[edi],ebx
        cmp     eax,055AA55AAh
        jne     Real_mode
        pop     eax
        mov     dword ptr es:[0Dh*4], eax
        popf    
        clc                             ;System is in Big Real Mode
        jmp     Exit_Ret

Real_mode:
        pop     eax
        mov     dword ptr es:[0Dh*4], eax
        popf
        stc                             ;System is in Real Mode
Exit_Ret:
        pop     ds
        pop     es
        pop     ebx
        pop     edi
        pop     eax
        ret        
Check_Big_Real_mode  ENDP

ENDIF

AhciDataStart   label word
AhciAccess AHCI_ACCESS (MKF_AHCI_CONTROLLER_COUNT) dup (<>)

OEM16_CSEG ENDS

END
;****************************************************************************
;****************************************************************************
;**                                                                        **
;**             (C)Copyright 1985-2014, American Megatrends, Inc.          **
;**                                                                        **
;**                          All Rights Reserved.                          **
;**                                                                        **
;**                 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093      **
;**                                                                        **
;**                          Phone (770)-246-8600                          **
;**                                                                        **
;****************************************************************************
;****************************************************************************