OSDN Git Service

wwww
[proj16/16.git] / 16 / v2 / source / verge / ENGINE / KEYBOARD.S
1 #\r
2 # Copyright (C) 1998 BJ Eirich (aka vecna)\r
3 # This program is free software; you can redistribute it and/or\r
4 # modify it under the terms of the GNU General Public License\r
5 # as published by the Free Software Foundation; either version 2\r
6 # of the License, or (at your option) any later version.\r
7 # This program is distributed in the hope that it will be useful,\r
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of\r
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  \r
10 # See the GNU General Public Lic\r
11 # See the GNU General Public License for more details.\r
12 # You should have received a copy of the GNU General Public License\r
13 # along with this program; if not, write to the Free Software\r
14 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.\r
15 #\r
16 \r
17                 .file   "keyboard.s"\r
18 \r
19                 .extern ___djgpp_base_address\r
20                 .extern ___djgpp_ds_alias\r
21                 .extern ___djgpp_dos_sel\r
22 \r
23  # public functions and variables:\r
24 \r
25                 .global _key\r
26                 .global _InitKeyboard\r
27                 .global _ShutdownKeyboard\r
28                 .global _keyboard_chain\r
29                 .global _last_pressed\r
30 \r
31                 .text\r
32 \r
33                 .align  4\r
34 \r
35 locking_region_start:\r
36 \r
37 _key:           .space  0x80, 0\r
38 _last_pressed:  .byte  0\r
39 old_vector:\r
40 old_vector_ofs: .long   0\r
41 old_vector_sel: .word   0\r
42 chain_flag:     .long   1\r
43 \r
44 \r
45                 .align  4\r
46 \r
47 handler_procedure:\r
48 \r
49  #\r
50  # .. will be called every time a key is pressed/released\r
51  #\r
52                 pushl   %eax\r
53                 pushl   %edx\r
54                 pushw   %ds\r
55  #\r
56  # Load DS with our data selector\r
57  #\r
58                 movw    %cs:___djgpp_ds_alias, %ds\r
59  #\r
60  # Read the scancode from keyboard port and update key[]\r
61  #\r
62                 inb     $0x60, %al\r
63                 movb    %al, %dl\r
64                 andl    $0x7f, %edx\r
65                 testb   $0x80, %al\r
66                 setz    _key(%edx)\r
67                 cmp     $127, %al\r
68                 ja      nolastpressed\r
69                 movb    %edx, _last_pressed\r
70 nolastpressed:\r
71 \r
72  #\r
73  # Chain if flag is set, otherwise do what's necessary and return\r
74  #\r
75                 cmpl    $0, chain_flag\r
76                 jne     handler_chain\r
77  #\r
78  # Acknowledge keyboard and interrupt contollers\r
79  #\r
80                 inb     $0x61, %al\r
81                 orb     $0x80, %al\r
82                 outb    %al, $0x61\r
83                 andb    $0x7f, %al\r
84                 outb    %al, $0x61\r
85                 movb    $0x20, %al\r
86                 outb    %al, $0x20\r
87 \r
88                 popw    %ds\r
89                 popl    %edx\r
90                 popl    %eax\r
91                 sti\r
92                 iret\r
93 \r
94                 .align  4\r
95 \r
96 handler_chain:  popw    %ds\r
97                 popl    %edx\r
98                 popl    %eax\r
99                 ljmp    %cs:(old_vector)\r
100 \r
101 locking_region_end:\r
102 \r
103 \r
104                 .align  4\r
105 _InitKeyboard:\r
106 \r
107  #\r
108  # int keyboard_init(void);\r
109  #\r
110  # Initializes the keyboard handler and hooks the keyboard interrupt.\r
111  # Returns -1 on failure, zero on success\r
112  #\r
113                 pushl   %esi\r
114                 pushl   %edi\r
115                 pushl   %ebx\r
116  #\r
117  # First, we need to lock the handler and memory it touches, so\r
118  # it doesn't get swapped out to disk.\r
119  #\r
120                 leal    locking_region_start, %ecx\r
121                 leal    locking_region_end, %edi\r
122                 subl    %ecx, %edi\r
123                 addl    ___djgpp_base_address, %ecx\r
124                 shldl   $16, %ecx, %ebx         # ecx -> bx:cx\r
125                 shldl   $16, %edi, %esi         # edi -> si:di\r
126                 movw    $0x0600, %ax            # lock linear region\r
127                 int     $0x31\r
128                 jc      init_error\r
129  #\r
130  # Now we need to save the old interrupt vector, so we can restore\r
131  # it later and also to know where to jump if chaining.\r
132  #\r
133                 movw    $0x0204, %ax            # get pm int vector\r
134                 movb    $0x09, %bl\r
135                 int     $0x31\r
136                 movw    %cx, old_vector_sel\r
137                 movl    %edx, old_vector_ofs\r
138  #\r
139  # Make sure we chain after initialization.\r
140  #\r
141                 movl    $1, chain_flag\r
142  #\r
143  # Set the interrupt vector to point to our handler.\r
144  #\r
145                 movw    %cs, %cx\r
146                 leal    handler_procedure, %edx\r
147                 movb    $0x09, %bl\r
148                 movw    $0x0205, %ax            # set pm int vector\r
149                 int     $0x31\r
150  #*\r
151  #* Actually we would have to unlock the locked region on failure\r
152  #* here. But since most programs would exit with an error message\r
153  #* in such case, there's no need to worry.\r
154  #*\r
155 \r
156 init_error:\r
157 \r
158  #\r
159  # This sets EAX to -1 if CF is set and to 0 atherwise\r
160  #\r
161                 movl    $0, %eax\r
162                 sbbl    $0, %eax\r
163 \r
164                 popl    %ebx\r
165                 popl    %edi\r
166                 popl    %esi\r
167                 ret\r
168 \r
169 \r
170                 .align 4\r
171 _ShutdownKeyboard:\r
172 \r
173  #\r
174  # void keyboard_close(void);\r
175  #\r
176  # Shuts the keyboard handler down.\r
177  #\r
178                 pushl   %esi\r
179                 pushl   %edi\r
180                 pushl   %ebx\r
181  #\r
182  # Unlock the region we locked at initialization\r
183  #\r
184                 leal    locking_region_start, %ecx\r
185                 leal    locking_region_end, %edi\r
186                 subl    %ecx, %edi\r
187                 addl    ___djgpp_base_address, %ecx\r
188                 shldl   $16, %ecx, %ebx\r
189                 shldl   $16, %edi, %esi\r
190                 movw    $0x0601, %ax            # unlock linear region\r
191                 int     $0x31\r
192  #\r
193  # Restore the interrupt vector to its previous value\r
194  #\r
195                 movw    old_vector_sel, %cx\r
196                 movl    old_vector_ofs, %edx\r
197                 movb    $0x09, %bl\r
198                 movw    $0x0205, %ax            # set pm int vector\r
199                 int     $0x31\r
200 \r
201                 popl    %ebx\r
202                 popl    %edi\r
203                 popl    %esi\r
204                 ret\r
205  #\r
206  # void keyboard_chain(int toggle);\r
207  #\r
208                 .align  4\r
209 _keyboard_chain:\r
210                 cmpl    $0, 4(%esp)\r
211                 je      chain_off\r
212 chain_on:\r
213 \r
214  #\r
215  # Set the chain_flag and clear BIOS shift/ctrl/alt status bits:\r
216  #\r
217                 movl    $1, chain_flag\r
218 \r
219                 push    %es\r
220                 movw    ___djgpp_dos_sel, %es\r
221                 andb    $0xf0, %es:0x417\r
222                 pop     %es\r
223                 jmp     chain_done\r
224 chain_off:\r
225                 movl    $0, chain_flag\r
226 chain_done:     ret\r
227 \r