root/kernel/chr_drv/keyboard.S

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

/* [previous][next][first][last][top][bottom][index][help] */