rev |
line source |
pascal@19515
|
1 ;***************************************************************
|
pascal@19515
|
2 ;****** This file is distributed under GPL
|
pascal@19515
|
3 ;***************************************************************
|
pascal@19515
|
4 ideal
|
pascal@19515
|
5 %crefref
|
pascal@19515
|
6 %noincl
|
pascal@19515
|
7 %nomacs
|
pascal@19515
|
8 p386
|
pascal@19515
|
9
|
pascal@19515
|
10 group DGROUP _TEXT,_DATA
|
pascal@19515
|
11 assume cs:DGROUP,ds:DGROUP
|
pascal@19515
|
12
|
pascal@19515
|
13 segment _DATA byte public use16 'DATA'
|
pascal@19515
|
14
|
pascal@19515
|
15 global die:near
|
pascal@19515
|
16 enable_a20_methods:
|
pascal@19515
|
17 dw _enable_a20_fast, _enable_a20_kbd, _enable_a20_xmm, die
|
pascal@19515
|
18 msg_a20 db "Can't enable A20",0
|
pascal@19515
|
19
|
pascal@19515
|
20 ends _DATA
|
pascal@19515
|
21
|
pascal@19515
|
22 segment _TEXT byte public use16 'CODE'
|
pascal@19515
|
23
|
pascal@19515
|
24 global xmm_driver:near
|
pascal@19515
|
25 global _enable_a20_xmm:near
|
pascal@19515
|
26
|
pascal@19515
|
27 ;***************************************************************
|
pascal@19515
|
28 ;void enable_a20_kbd();
|
pascal@19515
|
29 ;***************************************************************
|
pascal@19515
|
30 proc _enable_a20_kbd near
|
pascal@19515
|
31
|
pascal@19515
|
32 call @@empty_8042
|
pascal@19515
|
33 mov al,0D1h ; command write
|
pascal@19515
|
34 out 64h,al
|
pascal@19515
|
35 call @@empty_8042
|
pascal@19515
|
36 mov al,0DFh ; A20 on
|
pascal@19515
|
37 out 60h,al
|
pascal@19515
|
38
|
pascal@19515
|
39 ; This routine checks that the keyboard command queue is empty
|
pascal@19515
|
40 ; (after emptying the output buffers)
|
pascal@19515
|
41 ; Some machines have delusions that the keyboard buffer is always full
|
pascal@19515
|
42 ; with no keyboard attached...
|
pascal@19515
|
43 ; If there is no keyboard controller, we will usually get 0xff
|
pascal@19515
|
44 ; to all the reads. With each IO taking a microsecond and
|
pascal@19515
|
45 ; a timeout of 100,000 iterations, this can take about half a
|
pascal@19515
|
46 ; second ("delay" == out to port 0x80). That should be ok,
|
pascal@19515
|
47 ; and should also be plenty of time for a real keyboard controller
|
pascal@19515
|
48 ; to empty.
|
pascal@19515
|
49
|
pascal@19515
|
50 @@empty_8042:
|
pascal@19515
|
51 xor cx,cx ; 64K iterations
|
pascal@19515
|
52 @@loop:
|
pascal@19515
|
53 call @@delay ; 8042 status port
|
pascal@19515
|
54 in al,64h ; output buffer?
|
pascal@19515
|
55 test al,1 ;
|
pascal@19515
|
56 jz @@no_output
|
pascal@19515
|
57 call @@delay ; yes: read it
|
pascal@19515
|
58 in al,60h ;
|
pascal@19515
|
59 jmp @@cont ;
|
pascal@19515
|
60 @@no_output:
|
pascal@19515
|
61 test al,2 ; is input buffer full?
|
pascal@19515
|
62 jz @@break ; no - break loop
|
pascal@19515
|
63 @@cont:
|
pascal@19515
|
64 loop @@loop
|
pascal@19515
|
65 @@break:
|
pascal@19515
|
66 ret
|
pascal@19515
|
67
|
pascal@19515
|
68 @@delay: out 80h,al
|
pascal@19515
|
69 ret
|
pascal@19515
|
70
|
pascal@19515
|
71 endp _enable_a20_kbd
|
pascal@19515
|
72
|
pascal@19515
|
73 ;***************************************************************
|
pascal@19515
|
74 ;void enable_a20_fast();
|
pascal@19515
|
75 ;***************************************************************
|
pascal@19515
|
76 proc _enable_a20_fast near
|
pascal@19515
|
77
|
pascal@19515
|
78 ; You must preserve the other bits here. Otherwise embarrasing things
|
pascal@19515
|
79 ; like laptops powering off on boot happen. Corrected version by Kira
|
pascal@19515
|
80 ; Brown from Linux 2.2
|
pascal@19515
|
81 in al,92h ;
|
pascal@19515
|
82 or al,02h ; "fast A20" version
|
pascal@19515
|
83 out 92h,al ; some chips have only this
|
pascal@19515
|
84 ret
|
pascal@19515
|
85
|
pascal@19515
|
86 endp _enable_a20_fast
|
pascal@19515
|
87
|
pascal@19515
|
88 ;***************************************************************
|
pascal@19515
|
89 ;int check_a20();
|
pascal@19515
|
90 ;***************************************************************
|
pascal@19515
|
91 proc _check_a20 near
|
pascal@19515
|
92
|
pascal@19515
|
93 ; From linux kernel setup.S:
|
pascal@19515
|
94 ; wait until a20 really *is* enabled; it can take a fair amount of
|
pascal@19515
|
95 ; time on certain systems; Toshiba Tecras are known to have this
|
pascal@19515
|
96 ; problem.
|
pascal@19515
|
97
|
pascal@19515
|
98 push ds es
|
pascal@19515
|
99 xor bx,bx
|
pascal@19515
|
100 mov ds,bx
|
pascal@19515
|
101 mov cx,0FFFFh
|
pascal@19515
|
102 mov es,cx
|
pascal@19515
|
103 a20lp:
|
pascal@19515
|
104 cli
|
pascal@19515
|
105 mov ax,0AA55h
|
pascal@19515
|
106 xchg al,[bx]
|
pascal@19515
|
107 xchg ah,[es:bx+10h]
|
pascal@19515
|
108 xchg al,[bx]
|
pascal@19515
|
109 xchg ah,[es:bx+10h]
|
pascal@19515
|
110 cmp al,55h
|
pascal@19515
|
111 sti
|
pascal@19515
|
112 a20ko:
|
pascal@19515
|
113 loopne a20lp
|
pascal@19515
|
114 xchg ax,cx
|
pascal@19515
|
115 pop es ds
|
pascal@19515
|
116 ret
|
pascal@19515
|
117
|
pascal@19515
|
118 endp _check_a20
|
pascal@19515
|
119
|
pascal@19515
|
120 ;***************************************************************
|
pascal@19515
|
121 ;void enable_a20_or_die();
|
pascal@19515
|
122 ;***************************************************************
|
pascal@19515
|
123 global _enable_a20_or_die:near
|
pascal@19515
|
124 proc _enable_a20_or_die near
|
pascal@19515
|
125
|
pascal@19515
|
126 push si
|
pascal@19515
|
127 mov si,offset enable_a20_methods
|
pascal@19515
|
128 jmp @@check
|
pascal@19515
|
129 @@loop:
|
pascal@19515
|
130 lodsw
|
pascal@19515
|
131 mov bx,offset msg_a20
|
pascal@19515
|
132 call ax
|
pascal@19515
|
133 @@check:
|
pascal@19515
|
134 call _check_a20
|
pascal@19515
|
135 jne @@loop
|
pascal@19515
|
136 pop si
|
pascal@19515
|
137 ret
|
pascal@19515
|
138
|
pascal@19515
|
139 endp _enable_a20_or_die
|
pascal@19515
|
140
|
pascal@19515
|
141 ends _TEXT
|
pascal@19515
|
142
|
pascal@19515
|
143 end
|
pascal@19515
|
144
|
pascal@19515
|
145 ;###### END OF FILE ############################################
|