|
|
1.1 root 1: /*
2: * keyboard.s
3: */
4:
5: .text
6: .globl _keyboard_interrupt
7:
8: /*
9: * these are for the keyboard read functions
10: */
11: size = 1024 /* must be a power of two ! And MUST be the same
12: as in tty_io.c !!!! */
13: head = 4
14: tail = 8
15: proc_list = 12
16: buf = 16
17:
18: mode: .byte 0 /* caps, alt, ctrl and shift mode */
19: leds: .byte 2 /* num-lock, caps, scroll-lock mode (nom-lock on) */
20: e0: .byte 0
21:
22: /*
23: * con_int is the real interrupt routine that reads the
24: * keyboard scan-code and converts it into the appropriate
25: * ascii character(s).
26: */
27: _keyboard_interrupt:
28: pushl %eax
29: pushl %ebx
30: pushl %ecx
31: pushl %edx
32: push %ds
33: push %es
34: movl $0x10,%eax
35: mov %ax,%ds
36: mov %ax,%es
37: xorl %al,%al /* %eax is scan code */
38: inb $0x60,%al
39: cmpb $0xe0,%al
40: je set_e0
41: cmpb $0xe1,%al
42: je set_e1
43: call key_table(,%eax,4)
44: movb $0,e0
45: e0_e1: inb $0x61,%al
46: jmp 1f
47: 1: jmp 1f
48: 1: orb $0x80,%al
49: jmp 1f
50: 1: jmp 1f
51: 1: outb %al,$0x61
52: jmp 1f
53: 1: jmp 1f
54: 1: andb $0x7F,%al
55: outb %al,$0x61
56: movb $0x20,%al
57: outb %al,$0x20
58: pushl $0
59: call _do_tty_interrupt
60: addl $4,%esp
61: pop %es
62: pop %ds
63: popl %edx
64: popl %ecx
65: popl %ebx
66: popl %eax
67: iret
68: set_e0: movb $1,e0
69: jmp e0_e1
70: set_e1: movb $2,e0
71: jmp e0_e1
72:
73: /*
74: * This routine fills the buffer with max 8 bytes, taken from
75: * %ebx:%eax. (%edx is high). The bytes are written in the
76: * order %al,%ah,%eal,%eah,%bl,%bh ... until %eax is zero.
77: */
78: put_queue:
79: pushl %ecx
80: pushl %edx
81: movl _table_list,%edx # read-queue for console
82: movl head(%edx),%ecx
83: 1: movb %al,buf(%edx,%ecx)
84: incl %ecx
85: andl $size-1,%ecx
86: cmpl tail(%edx),%ecx # buffer full - discard everything
87: je 3f
88: shrdl $8,%ebx,%eax
89: je 2f
90: shrl $8,%ebx
91: jmp 1b
92: 2: movl %ecx,head(%edx)
93: movl proc_list(%edx),%ecx
94: testl %ecx,%ecx
95: je 3f
96: movl $0,(%ecx)
97: 3: popl %edx
98: popl %ecx
99: ret
100:
101: ctrl: movb $0x04,%al
102: jmp 1f
103: alt: movb $0x10,%al
104: 1: cmpb $0,e0
105: je 2f
106: addb %al,%al
107: 2: orb %al,mode
108: ret
109: unctrl: movb $0x04,%al
110: jmp 1f
111: unalt: movb $0x10,%al
112: 1: cmpb $0,e0
113: je 2f
114: addb %al,%al
115: 2: notb %al
116: andb %al,mode
117: ret
118:
119: lshift:
120: orb $0x01,mode
121: ret
122: unlshift:
123: andb $0xfe,mode
124: ret
125: rshift:
126: orb $0x02,mode
127: ret
128: unrshift:
129: andb $0xfd,mode
130: ret
131:
132: caps: testb $0x80,mode
133: jne 1f
134: xorb $4,leds
135: xorb $0x40,mode
136: orb $0x80,mode
137: set_leds:
138: call kb_wait
139: movb $0xed,%al /* set leds command */
140: outb %al,$0x60
141: call kb_wait
142: movb leds,%al
143: outb %al,$0x60
144: ret
145: uncaps: andb $0x7f,mode
146: ret
147: scroll:
148: xorb $1,leds
149: jmp set_leds
150: num: xorb $2,leds
151: jmp set_leds
152:
153: /*
154: * curosr-key/numeric keypad cursor keys are handled here.
155: * checking for numeric keypad etc.
156: */
157: cursor:
158: subb $0x47,%al
159: jb 1f
160: cmpb $12,%al
161: ja 1f
162: jne cur2 /* check for ctrl-alt-del */
163: testb $0x0c,mode
164: je cur2
165: testb $0x30,mode
166: jne reboot
167: cur2: cmpb $0x01,e0 /* e0 forces cursor movement */
168: je cur
169: testb $0x02,leds /* not num-lock forces cursor */
170: je cur
171: testb $0x03,mode /* shift forces cursor */
172: jne cur
173: xorl %ebx,%ebx
174: movb num_table(%eax),%al
175: jmp put_queue
176: 1: ret
177:
178: cur: movb cur_table(%eax),%al
179: cmpb $'9,%al
180: ja ok_cur
181: movb $'~,%ah
182: ok_cur: shll $16,%eax
183: movw $0x5b1b,%ax
184: xorl %ebx,%ebx
185: jmp put_queue
186:
187: num_table:
188: .ascii "789 456 1230,"
189: cur_table:
190: .ascii "HA5 DGC YB623"
191:
192: /*
193: * this routine handles function keys
194: */
195: func:
196: subb $0x3B,%al
197: jb end_func
198: cmpb $9,%al
199: jbe ok_func
200: subb $18,%al
201: cmpb $10,%al
202: jb end_func
203: cmpb $11,%al
204: ja end_func
205: ok_func:
206: cmpl $4,%ecx /* check that there is enough room */
207: jl end_func
208: movl func_table(,%eax,4),%eax
209: xorl %ebx,%ebx
210: jmp put_queue
211: end_func:
212: ret
213:
214: /*
215: * function keys send F1:'esc [ [ A' F2:'esc [ [ B' etc.
216: */
217: func_table:
218: .long 0x415b5b1b,0x425b5b1b,0x435b5b1b,0x445b5b1b
219: .long 0x455b5b1b,0x465b5b1b,0x475b5b1b,0x485b5b1b
220: .long 0x495b5b1b,0x4a5b5b1b,0x4b5b5b1b,0x4c5b5b1b
221:
222: key_map:
223: .byte 0,27
224: .ascii "1234567890+'"
225: .byte 127,9
226: .ascii "qwertyuiop}"
227: .byte 0,10,0
228: .ascii "asdfghjkl|{"
229: .byte 0,0
230: .ascii "'zxcvbnm,.-"
231: .byte 0,'*,0,32 /* 36-39 */
232: .fill 16,1,0 /* 3A-49 */
233: .byte '-,0,0,0,'+ /* 4A-4E */
234: .byte 0,0,0,0,0,0,0 /* 4F-55 */
235: .byte '<
236: .fill 10,1,0
237:
238: shift_map:
239: .byte 0,27
240: .ascii "!\"#$%&/()=?`"
241: .byte 127,9
242: .ascii "QWERTYUIOP]^"
243: .byte 10,0
244: .ascii "ASDFGHJKL\\["
245: .byte 0,0
246: .ascii "*ZXCVBNM;:_"
247: .byte 0,'*,0,32 /* 36-39 */
248: .fill 16,1,0 /* 3A-49 */
249: .byte '-,0,0,0,'+ /* 4A-4E */
250: .byte 0,0,0,0,0,0,0 /* 4F-55 */
251: .byte '>
252: .fill 10,1,0
253:
254: alt_map:
255: .byte 0,0
256: .ascii "\0@\0$\0\0{[]}\\\0"
257: .byte 0,0
258: .byte 0,0,0,0,0,0,0,0,0,0,0
259: .byte '~,10,0
260: .byte 0,0,0,0,0,0,0,0,0,0,0
261: .byte 0,0
262: .byte 0,0,0,0,0,0,0,0,0,0,0
263: .byte 0,0,0,0 /* 36-39 */
264: .fill 16,1,0 /* 3A-49 */
265: .byte 0,0,0,0,0 /* 4A-4E */
266: .byte 0,0,0,0,0,0,0 /* 4F-55 */
267: .byte '|
268: .fill 10,1,0
269:
270: /*
271: * do_self handles "normal" keys, ie keys that don't change meaning
272: * and which have just one character returns.
273: */
274: do_self:
275: lea alt_map,%ebx
276: testb $0x20,mode /* alt-gr */
277: jne 1f
278: lea shift_map,%ebx
279: testb $0x03,mode
280: jne 1f
281: lea key_map,%ebx
282: 1: movb (%ebx,%eax),%al
283: orb %al,%al
284: je none
285: testb $0x4c,mode /* ctrl or caps */
286: je 2f
287: cmpb $'a,%al
288: jb 2f
289: cmpb $'z,%al
290: ja 2f
291: subb $32,%al
292: 2: testb $0x0c,mode /* ctrl */
293: je 3f
294: cmpb $64,%al
295: jb 3f
296: cmpb $64+32,%al
297: jae 3f
298: subb $64,%al
299: 3: testb $0x10,mode /* left alt */
300: je 4f
301: orb $0x80,%al
302: 4: andl $0xff,%eax
303: xorl %ebx,%ebx
304: call put_queue
305: none: ret
306:
307: /*
308: * minus has a routine of it's own, as a 'E0h' before
309: * the scan code for minus means that the numeric keypad
310: * slash was pushed.
311: */
312: minus: cmpb $1,e0
313: jne do_self
314: movl $'/,%eax
315: xorl %ebx,%ebx
316: jmp put_queue
317:
318: /*
319: * This table decides which routine to call when a scan-code has been
320: * gotten. Most routines just call do_self, or none, depending if
321: * they are make or break.
322: */
323: key_table:
324: .long none,do_self,do_self,do_self /* 00-03 s0 esc 1 2 */
325: .long do_self,do_self,do_self,do_self /* 04-07 3 4 5 6 */
326: .long do_self,do_self,do_self,do_self /* 08-0B 7 8 9 0 */
327: .long do_self,do_self,do_self,do_self /* 0C-0F + ' bs tab */
328: .long do_self,do_self,do_self,do_self /* 10-13 q w e r */
329: .long do_self,do_self,do_self,do_self /* 14-17 t y u i */
330: .long do_self,do_self,do_self,do_self /* 18-1B o p } ^ */
331: .long do_self,ctrl,do_self,do_self /* 1C-1F enter ctrl a s */
332: .long do_self,do_self,do_self,do_self /* 20-23 d f g h */
333: .long do_self,do_self,do_self,do_self /* 24-27 j k l | */
334: .long do_self,do_self,lshift,do_self /* 28-2B { para lshift , */
335: .long do_self,do_self,do_self,do_self /* 2C-2F z x c v */
336: .long do_self,do_self,do_self,do_self /* 30-33 b n m , */
337: .long do_self,minus,rshift,do_self /* 34-37 . - rshift * */
338: .long alt,do_self,caps,func /* 38-3B alt sp caps f1 */
339: .long func,func,func,func /* 3C-3F f2 f3 f4 f5 */
340: .long func,func,func,func /* 40-43 f6 f7 f8 f9 */
341: .long func,num,scroll,cursor /* 44-47 f10 num scr home */
342: .long cursor,cursor,do_self,cursor /* 48-4B up pgup - left */
343: .long cursor,cursor,do_self,cursor /* 4C-4F n5 right + end */
344: .long cursor,cursor,cursor,cursor /* 50-53 dn pgdn ins del */
345: .long none,none,do_self,func /* 54-57 sysreq ? < f11 */
346: .long func,none,none,none /* 58-5B f12 ? ? ? */
347: .long none,none,none,none /* 5C-5F ? ? ? ? */
348: .long none,none,none,none /* 60-63 ? ? ? ? */
349: .long none,none,none,none /* 64-67 ? ? ? ? */
350: .long none,none,none,none /* 68-6B ? ? ? ? */
351: .long none,none,none,none /* 6C-6F ? ? ? ? */
352: .long none,none,none,none /* 70-73 ? ? ? ? */
353: .long none,none,none,none /* 74-77 ? ? ? ? */
354: .long none,none,none,none /* 78-7B ? ? ? ? */
355: .long none,none,none,none /* 7C-7F ? ? ? ? */
356: .long none,none,none,none /* 80-83 ? br br br */
357: .long none,none,none,none /* 84-87 br br br br */
358: .long none,none,none,none /* 88-8B br br br br */
359: .long none,none,none,none /* 8C-8F br br br br */
360: .long none,none,none,none /* 90-93 br br br br */
361: .long none,none,none,none /* 94-97 br br br br */
362: .long none,none,none,none /* 98-9B br br br br */
363: .long none,unctrl,none,none /* 9C-9F br unctrl br br */
364: .long none,none,none,none /* A0-A3 br br br br */
365: .long none,none,none,none /* A4-A7 br br br br */
366: .long none,none,unlshift,none /* A8-AB br br unlshift br */
367: .long none,none,none,none /* AC-AF br br br br */
368: .long none,none,none,none /* B0-B3 br br br br */
369: .long none,none,unrshift,none /* B4-B7 br br unrshift br */
370: .long unalt,none,uncaps,none /* B8-BB unalt br uncaps br */
371: .long none,none,none,none /* BC-BF br br br br */
372: .long none,none,none,none /* C0-C3 br br br br */
373: .long none,none,none,none /* C4-C7 br br br br */
374: .long none,none,none,none /* C8-CB br br br br */
375: .long none,none,none,none /* CC-CF br br br br */
376: .long none,none,none,none /* D0-D3 br br br br */
377: .long none,none,none,none /* D4-D7 br br br br */
378: .long none,none,none,none /* D8-DB br ? ? ? */
379: .long none,none,none,none /* DC-DF ? ? ? ? */
380: .long none,none,none,none /* E0-E3 e0 e1 ? ? */
381: .long none,none,none,none /* E4-E7 ? ? ? ? */
382: .long none,none,none,none /* E8-EB ? ? ? ? */
383: .long none,none,none,none /* EC-EF ? ? ? ? */
384: .long none,none,none,none /* F0-F3 ? ? ? ? */
385: .long none,none,none,none /* F4-F7 ? ? ? ? */
386: .long none,none,none,none /* F8-FB ? ? ? ? */
387: .long none,none,none,none /* FC-FF ? ? ? ? */
388:
389: /*
390: * kb_wait waits for the keyboard controller buffer to empty.
391: * there is no timeout - if the buffer doesn't empty, we hang.
392: */
393: kb_wait:
394: pushl %eax
395: 1: inb $0x64,%al
396: testb $0x02,%al
397: jne 1b
398: popl %eax
399: ret
400: /*
401: * This routine reboots the machine by asking the keyboard
402: * controller to pulse the reset-line low.
403: */
404: reboot:
405: call kb_wait
406: movw $0x1234,0x472 /* don't do memory check */
407: movb $0xfc,%al /* pulse reset and A20 low */
408: outb %al,$0x64
409: die: jmp die
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.