summaryrefslogtreecommitdiffstats
path: root/src/kernel/chr_drv/kb.S
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel/chr_drv/kb.S')
-rw-r--r--src/kernel/chr_drv/kb.S588
1 files changed, 588 insertions, 0 deletions
diff --git a/src/kernel/chr_drv/kb.S b/src/kernel/chr_drv/kb.S
new file mode 100644
index 0000000..ffd28cf
--- /dev/null
+++ b/src/kernel/chr_drv/kb.S
@@ -0,0 +1,588 @@
1/*
2 * linux/kernel/keyboard.S
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7/*
8 * Thanks to Alfred Leung for US keyboard patches
9 * Wolfgang Thiel for German keyboard patches
10 * Marc Corsini for the French keyboard
11 */
12
13#include <linux/config.h>
14
15.text
16.globl keyboard_interrupt
17
18/*
19 * these are for the keyboard read functions
20 */
21size = 1024 /* must be a power of two ! And MUST be the same
22 as in tty_io.c !!!! */
23head = 4
24tail = 8
25proc_list = 12
26buf = 16
27
28mode: .byte 0 /* caps, alt, ctrl and shift mode */
29leds: .byte 2 /* num-lock, caps, scroll-lock mode (nom-lock on) */
30e0: .byte 0
31
32/*
33 * con_int is the real interrupt routine that reads the
34 * keyboard scan-code and converts it into the appropriate
35 * ascii character(s).
36 */
37keyboard_interrupt:
38 pushl %eax
39 pushl %ebx
40 pushl %ecx
41 pushl %edx
42 push %ds
43 push %es
44 movl $0x10,%eax
45 mov %ax,%ds
46 mov %ax,%es
47 xor %al,%al /* %eax is scan code */
48 inb $0x60,%al
49 cmpb $0xe0,%al
50 je set_e0
51 cmpb $0xe1,%al
52 je set_e1
53 call *key_table(,%eax,4)
54 movb $0,e0
55e0_e1: inb $0x61,%al
56 jmp 1f
571: jmp 1f
581: orb $0x80,%al
59 jmp 1f
601: jmp 1f
611: outb %al,$0x61
62 jmp 1f
631: jmp 1f
641: andb $0x7F,%al
65 outb %al,$0x61
66 movb $0x20,%al
67 outb %al,$0x20
68 pushl $0
69 call do_tty_interrupt
70 addl $4,%esp
71 pop %es
72 pop %ds
73 popl %edx
74 popl %ecx
75 popl %ebx
76 popl %eax
77 iret
78set_e0: movb $1,e0
79 jmp e0_e1
80set_e1: movb $2,e0
81 jmp e0_e1
82
83/*
84 * This routine fills the buffer with max 8 bytes, taken from
85 * %ebx:%eax. (%edx is high). The bytes are written in the
86 * order %al,%ah,%eal,%eah,%bl,%bh ... until %eax is zero.
87 */
88put_queue:
89 pushl %ecx
90 pushl %edx
91 movl table_list,%edx # read-queue for console
92 movl head(%edx),%ecx
931: movb %al,buf(%edx,%ecx)
94 incl %ecx
95 andl $size-1,%ecx
96 cmpl tail(%edx),%ecx # buffer full - discard everything
97 je 3f
98 shrdl $8,%ebx,%eax
99 je 2f
100 shrl $8,%ebx
101 jmp 1b
1022: movl %ecx,head(%edx)
103 movl proc_list(%edx),%ecx
104 testl %ecx,%ecx
105 je 3f
106 movl $0,(%ecx)
1073: popl %edx
108 popl %ecx
109 ret
110
111ctrl: movb $0x04,%al
112 jmp 1f
113alt: movb $0x10,%al
1141: cmpb $0,e0
115 je 2f
116 addb %al,%al
1172: orb %al,mode
118 ret
119unctrl: movb $0x04,%al
120 jmp 1f
121unalt: movb $0x10,%al
1221: cmpb $0,e0
123 je 2f
124 addb %al,%al
1252: notb %al
126 andb %al,mode
127 ret
128
129lshift:
130 orb $0x01,mode
131 ret
132unlshift:
133 andb $0xfe,mode
134 ret
135rshift:
136 orb $0x02,mode
137 ret
138unrshift:
139 andb $0xfd,mode
140 ret
141
142caps: testb $0x80,mode
143 jne 1f
144 xorb $4,leds
145 xorb $0x40,mode
146 orb $0x80,mode
147set_leds:
148 call kb_wait
149 movb $0xed,%al /* set leds command */
150 outb %al,$0x60
151 call kb_wait
152 movb leds,%al
153 outb %al,$0x60
154 ret
155uncaps: andb $0x7f,mode
156 ret
157scroll:
158 xorb $1,leds
159 jmp set_leds
160num: xorb $2,leds
161 jmp set_leds
162
163/*
164 * curosr-key/numeric keypad cursor keys are handled here.
165 * checking for numeric keypad etc.
166 */
167cursor:
168 subb $0x47,%al
169 jb 1f
170 cmpb $12,%al
171 ja 1f
172 jne cur2 /* check for ctrl-alt-del */
173 testb $0x0c,mode
174 je cur2
175 testb $0x30,mode
176 jne reboot
177cur2: cmpb $0x01,e0 /* e0 forces cursor movement */
178 je cur
179 testb $0x02,leds /* not num-lock forces cursor */
180 je cur
181 testb $0x03,mode /* shift forces cursor */
182 jne cur
183 xorl %ebx,%ebx
184 movb num_table(%eax),%al
185 jmp put_queue
1861: ret
187
188cur: movb cur_table(%eax),%al
189 cmpb $'9,%al
190 ja ok_cur
191 movb $'~,%ah
192ok_cur: shll $16,%eax
193 movw $0x5b1b,%ax
194 xorl %ebx,%ebx
195 jmp put_queue
196
197#if defined(KBD_FR)
198num_table:
199 .ascii "789 456 1230."
200#else
201num_table:
202 .ascii "789 456 1230,"
203#endif
204cur_table:
205 .ascii "HA5 DGC YB623"
206
207/*
208 * this routine handles function keys
209 */
210func:
211 pushl %eax
212 pushl %ecx
213 pushl %edx
214 call show_stat
215 popl %edx
216 popl %ecx
217 popl %eax
218 subb $0x3B,%al
219 jb end_func
220 cmpb $9,%al
221 jbe ok_func
222 subb $18,%al
223 cmpb $10,%al
224 jb end_func
225 cmpb $11,%al
226 ja end_func
227ok_func:
228 cmpl $4,%ecx /* check that there is enough room */
229 jl end_func
230 movl func_table(,%eax,4),%eax
231 xorl %ebx,%ebx
232 jmp put_queue
233end_func:
234 ret
235
236/*
237 * function keys send F1:'esc [ [ A' F2:'esc [ [ B' etc.
238 */
239func_table:
240 .long 0x415b5b1b,0x425b5b1b,0x435b5b1b,0x445b5b1b
241 .long 0x455b5b1b,0x465b5b1b,0x475b5b1b,0x485b5b1b
242 .long 0x495b5b1b,0x4a5b5b1b,0x4b5b5b1b,0x4c5b5b1b
243
244#if defined(KBD_FINNISH)
245key_map:
246 .byte 0,27
247 .ascii "1234567890+'"
248 .byte 127,9
249 .ascii "qwertyuiop}"
250 .byte 0,13,0
251 .ascii "asdfghjkl|{"
252 .byte 0,0
253 .ascii "'zxcvbnm,.-"
254 .byte 0,'*,0,32 /* 36-39 */
255 .fill 16,1,0 /* 3A-49 */
256 .byte '-,0,0,0,'+ /* 4A-4E */
257 .byte 0,0,0,0,0,0,0 /* 4F-55 */
258 .byte '<
259 .fill 10,1,0
260
261shift_map:
262 .byte 0,27
263 .ascii "!\"#$%&/()=?`"
264 .byte 127,9
265 .ascii "QWERTYUIOP]^"
266 .byte 13,0
267 .ascii "ASDFGHJKL\\["
268 .byte 0,0
269 .ascii "*ZXCVBNM;:_"
270 .byte 0,'*,0,32 /* 36-39 */
271 .fill 16,1,0 /* 3A-49 */
272 .byte '-,0,0,0,'+ /* 4A-4E */
273 .byte 0,0,0,0,0,0,0 /* 4F-55 */
274 .byte '>
275 .fill 10,1,0
276
277alt_map:
278 .byte 0,0
279 .ascii "\0@\0$\0\0{[]}\\\0"
280 .byte 0,0
281 .byte 0,0,0,0,0,0,0,0,0,0,0
282 .byte '~,13,0
283 .byte 0,0,0,0,0,0,0,0,0,0,0
284 .byte 0,0
285 .byte 0,0,0,0,0,0,0,0,0,0,0
286 .byte 0,0,0,0 /* 36-39 */
287 .fill 16,1,0 /* 3A-49 */
288 .byte 0,0,0,0,0 /* 4A-4E */
289 .byte 0,0,0,0,0,0,0 /* 4F-55 */
290 .byte '|
291 .fill 10,1,0
292
293#elif defined(KBD_US)
294
295key_map:
296 .byte 0,27
297 .ascii "1234567890-="
298 .byte 127,9
299 .ascii "qwertyuiop[]"
300 .byte 13,0
301 .ascii "asdfghjkl;'"
302 .byte '`,0
303 .ascii "\\zxcvbnm,./"
304 .byte 0,'*,0,32 /* 36-39 */
305 .fill 16,1,0 /* 3A-49 */
306 .byte '-,0,0,0,'+ /* 4A-4E */
307 .byte 0,0,0,0,0,0,0 /* 4F-55 */
308 .byte '<
309 .fill 10,1,0
310
311
312shift_map:
313 .byte 0,27
314 .ascii "!@#$%^&*()_+"
315 .byte 127,9
316 .ascii "QWERTYUIOP{}"
317 .byte 13,0
318 .ascii "ASDFGHJKL:\""
319 .byte '~,0
320 .ascii "|ZXCVBNM<>?"
321 .byte 0,'*,0,32 /* 36-39 */
322 .fill 16,1,0 /* 3A-49 */
323 .byte '-,0,0,0,'+ /* 4A-4E */
324 .byte 0,0,0,0,0,0,0 /* 4F-55 */
325 .byte '>
326 .fill 10,1,0
327
328alt_map:
329 .byte 0,0
330 .ascii "\0@\0$\0\0{[]}\\\0"
331 .byte 0,0
332 .byte 0,0,0,0,0,0,0,0,0,0,0
333 .byte '~,13,0
334 .byte 0,0,0,0,0,0,0,0,0,0,0
335 .byte 0,0
336 .byte 0,0,0,0,0,0,0,0,0,0,0
337 .byte 0,0,0,0 /* 36-39 */
338 .fill 16,1,0 /* 3A-49 */
339 .byte 0,0,0,0,0 /* 4A-4E */
340 .byte 0,0,0,0,0,0,0 /* 4F-55 */
341 .byte '|
342 .fill 10,1,0
343
344#elif defined(KBD_GR)
345
346key_map:
347 .byte 0,27
348 .ascii "1234567890\\'"
349 .byte 127,9
350 .ascii "qwertzuiop@+"
351 .byte 13,0
352 .ascii "asdfghjkl[]^"
353 .byte 0,'#
354 .ascii "yxcvbnm,.-"
355 .byte 0,'*,0,32 /* 36-39 */
356 .fill 16,1,0 /* 3A-49 */
357 .byte '-,0,0,0,'+ /* 4A-4E */
358 .byte 0,0,0,0,0,0,0 /* 4F-55 */
359 .byte '<
360 .fill 10,1,0
361
362
363shift_map:
364 .byte 0,27
365 .ascii "!\"#$%&/()=?`"
366 .byte 127,9
367 .ascii "QWERTZUIOP\\*"
368 .byte 13,0
369 .ascii "ASDFGHJKL{}~"
370 .byte 0,''
371 .ascii "YXCVBNM;:_"
372 .byte 0,'*,0,32 /* 36-39 */
373 .fill 16,1,0 /* 3A-49 */
374 .byte '-,0,0,0,'+ /* 4A-4E */
375 .byte 0,0,0,0,0,0,0 /* 4F-55 */
376 .byte '>
377 .fill 10,1,0
378
379alt_map:
380 .byte 0,0
381 .ascii "\0@\0$\0\0{[]}\\\0"
382 .byte 0,0
383 .byte '@,0,0,0,0,0,0,0,0,0,0
384 .byte '~,13,0
385 .byte 0,0,0,0,0,0,0,0,0,0,0
386 .byte 0,0
387 .byte 0,0,0,0,0,0,0,0,0,0,0
388 .byte 0,0,0,0 /* 36-39 */
389 .fill 16,1,0 /* 3A-49 */
390 .byte 0,0,0,0,0 /* 4A-4E */
391 .byte 0,0,0,0,0,0,0 /* 4F-55 */
392 .byte '|
393 .fill 10,1,0
394
395
396#elif defined(KBD_FR)
397
398key_map:
399 .byte 0,27
400 .ascii "&{\"'(-}_/@)="
401 .byte 127,9
402 .ascii "azertyuiop^$"
403 .byte 13,0
404 .ascii "qsdfghjklm|"
405 .byte '`,0,42 /* coin sup gauche, don't know, [*|mu] */
406 .ascii "wxcvbn,;:!"
407 .byte 0,'*,0,32 /* 36-39 */
408 .fill 16,1,0 /* 3A-49 */
409 .byte '-,0,0,0,'+ /* 4A-4E */
410 .byte 0,0,0,0,0,0,0 /* 4F-55 */
411 .byte '<
412 .fill 10,1,0
413
414shift_map:
415 .byte 0,27
416 .ascii "1234567890]+"
417 .byte 127,9
418 .ascii "AZERTYUIOP<>"
419 .byte 13,0
420 .ascii "QSDFGHJKLM%"
421 .byte '~,0,'#
422 .ascii "WXCVBN?./\\"
423 .byte 0,'*,0,32 /* 36-39 */
424 .fill 16,1,0 /* 3A-49 */
425 .byte '-,0,0,0,'+ /* 4A-4E */
426 .byte 0,0,0,0,0,0,0 /* 4F-55 */
427 .byte '>
428 .fill 10,1,0
429
430alt_map:
431 .byte 0,0
432 .ascii "\0~#{[|`\\^@]}"
433 .byte 0,0
434 .byte '@,0,0,0,0,0,0,0,0,0,0
435 .byte '~,13,0
436 .byte 0,0,0,0,0,0,0,0,0,0,0
437 .byte 0,0
438 .byte 0,0,0,0,0,0,0,0,0,0,0
439 .byte 0,0,0,0 /* 36-39 */
440 .fill 16,1,0 /* 3A-49 */
441 .byte 0,0,0,0,0 /* 4A-4E */
442 .byte 0,0,0,0,0,0,0 /* 4F-55 */
443 .byte '|
444 .fill 10,1,0
445
446#else
447#error "KBD-type not defined"
448#endif
449/*
450 * do_self handles "normal" keys, ie keys that don't change meaning
451 * and which have just one character returns.
452 */
453do_self:
454 lea alt_map,%ebx
455 testb $0x20,mode /* alt-gr */
456 jne 1f
457 lea shift_map,%ebx
458 testb $0x03,mode
459 jne 1f
460 lea key_map,%ebx
4611: movb (%ebx,%eax),%al
462 orb %al,%al
463 je none
464 testb $0x4c,mode /* ctrl or caps */
465 je 2f
466 cmpb $'a,%al
467 jb 2f
468 cmpb $'},%al
469 ja 2f
470 subb $32,%al
4712: testb $0x0c,mode /* ctrl */
472 je 3f
473 cmpb $64,%al
474 jb 3f
475 cmpb $64+32,%al
476 jae 3f
477 subb $64,%al
4783: testb $0x10,mode /* left alt */
479 je 4f
480 orb $0x80,%al
4814: andl $0xff,%eax
482 xorl %ebx,%ebx
483 call put_queue
484none: ret
485
486/*
487 * minus has a routine of it's own, as a 'E0h' before
488 * the scan code for minus means that the numeric keypad
489 * slash was pushed.
490 */
491minus: cmpb $1,e0
492 jne do_self
493 movl $'/,%eax
494 xorl %ebx,%ebx
495 jmp put_queue
496
497/*
498 * This table decides which routine to call when a scan-code has been
499 * gotten. Most routines just call do_self, or none, depending if
500 * they are make or break.
501 */
502key_table:
503 .long none,do_self,do_self,do_self /* 00-03 s0 esc 1 2 */
504 .long do_self,do_self,do_self,do_self /* 04-07 3 4 5 6 */
505 .long do_self,do_self,do_self,do_self /* 08-0B 7 8 9 0 */
506 .long do_self,do_self,do_self,do_self /* 0C-0F + ' bs tab */
507 .long do_self,do_self,do_self,do_self /* 10-13 q w e r */
508 .long do_self,do_self,do_self,do_self /* 14-17 t y u i */
509 .long do_self,do_self,do_self,do_self /* 18-1B o p } ^ */
510 .long do_self,ctrl,do_self,do_self /* 1C-1F enter ctrl a s */
511 .long do_self,do_self,do_self,do_self /* 20-23 d f g h */
512 .long do_self,do_self,do_self,do_self /* 24-27 j k l | */
513 .long do_self,do_self,lshift,do_self /* 28-2B { para lshift , */
514 .long do_self,do_self,do_self,do_self /* 2C-2F z x c v */
515 .long do_self,do_self,do_self,do_self /* 30-33 b n m , */
516 .long do_self,minus,rshift,do_self /* 34-37 . - rshift * */
517 .long alt,do_self,caps,func /* 38-3B alt sp caps f1 */
518 .long func,func,func,func /* 3C-3F f2 f3 f4 f5 */
519 .long func,func,func,func /* 40-43 f6 f7 f8 f9 */
520 .long func,num,scroll,cursor /* 44-47 f10 num scr home */
521 .long cursor,cursor,do_self,cursor /* 48-4B up pgup - left */
522 .long cursor,cursor,do_self,cursor /* 4C-4F n5 right + end */
523 .long cursor,cursor,cursor,cursor /* 50-53 dn pgdn ins del */
524 .long none,none,do_self,func /* 54-57 sysreq ? < f11 */
525 .long func,none,none,none /* 58-5B f12 ? ? ? */
526 .long none,none,none,none /* 5C-5F ? ? ? ? */
527 .long none,none,none,none /* 60-63 ? ? ? ? */
528 .long none,none,none,none /* 64-67 ? ? ? ? */
529 .long none,none,none,none /* 68-6B ? ? ? ? */
530 .long none,none,none,none /* 6C-6F ? ? ? ? */
531 .long none,none,none,none /* 70-73 ? ? ? ? */
532 .long none,none,none,none /* 74-77 ? ? ? ? */
533 .long none,none,none,none /* 78-7B ? ? ? ? */
534 .long none,none,none,none /* 7C-7F ? ? ? ? */
535 .long none,none,none,none /* 80-83 ? br br br */
536 .long none,none,none,none /* 84-87 br br br br */
537 .long none,none,none,none /* 88-8B br br br br */
538 .long none,none,none,none /* 8C-8F br br br br */
539 .long none,none,none,none /* 90-93 br br br br */
540 .long none,none,none,none /* 94-97 br br br br */
541 .long none,none,none,none /* 98-9B br br br br */
542 .long none,unctrl,none,none /* 9C-9F br unctrl br br */
543 .long none,none,none,none /* A0-A3 br br br br */
544 .long none,none,none,none /* A4-A7 br br br br */
545 .long none,none,unlshift,none /* A8-AB br br unlshift br */
546 .long none,none,none,none /* AC-AF br br br br */
547 .long none,none,none,none /* B0-B3 br br br br */
548 .long none,none,unrshift,none /* B4-B7 br br unrshift br */
549 .long unalt,none,uncaps,none /* B8-BB unalt br uncaps br */
550 .long none,none,none,none /* BC-BF br br br br */
551 .long none,none,none,none /* C0-C3 br br br br */
552 .long none,none,none,none /* C4-C7 br br br br */
553 .long none,none,none,none /* C8-CB br br br br */
554 .long none,none,none,none /* CC-CF br br br br */
555 .long none,none,none,none /* D0-D3 br br br br */
556 .long none,none,none,none /* D4-D7 br br br br */
557 .long none,none,none,none /* D8-DB br ? ? ? */
558 .long none,none,none,none /* DC-DF ? ? ? ? */
559 .long none,none,none,none /* E0-E3 e0 e1 ? ? */
560 .long none,none,none,none /* E4-E7 ? ? ? ? */
561 .long none,none,none,none /* E8-EB ? ? ? ? */
562 .long none,none,none,none /* EC-EF ? ? ? ? */
563 .long none,none,none,none /* F0-F3 ? ? ? ? */
564 .long none,none,none,none /* F4-F7 ? ? ? ? */
565 .long none,none,none,none /* F8-FB ? ? ? ? */
566 .long none,none,none,none /* FC-FF ? ? ? ? */
567
568/*
569 * kb_wait waits for the keyboard controller buffer to empty.
570 * there is no timeout - if the buffer doesn't empty, we hang.
571 */
572kb_wait:
573 pushl %eax
5741: inb $0x64,%al
575 testb $0x02,%al
576 jne 1b
577 popl %eax
578 ret
579/*
580 * This routine reboots the machine by asking the keyboard
581 * controller to pulse the reset-line low.
582 */
583reboot:
584 call kb_wait
585 movw $0x1234,0x472 /* don't do memory check */
586 movb $0xfc,%al /* pulse reset and A20 low */
587 outb %al,$0x64
588die: jmp die