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  *              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  */
  21 size    = 1024          /* must be a power of two ! And MUST be the same
  22                            as in tty_io.c !!!! */
  23 head = 4
  24 tail = 8
  25 proc_list = 12
  26 buf = 16
  27 
  28 mode:   .byte 0         /* caps, alt, ctrl and shift mode */
  29 leds:   .byte 2         /* num-lock, caps, scroll-lock mode (nom-lock on) */
  30 e0:     .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  */
  37 _keyboard_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         xorl %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
  55 e0_e1:  inb $0x61,%al
  56         jmp 1f
  57 1:      jmp 1f
  58 1:      orb $0x80,%al
  59         jmp 1f
  60 1:      jmp 1f
  61 1:      outb %al,$0x61
  62         jmp 1f
  63 1:      jmp 1f
  64 1:      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
  78 set_e0: movb $1,e0
  79         jmp e0_e1
  80 set_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  */
  88 put_queue:
  89         pushl %ecx
  90         pushl %edx
  91         movl _table_list,%edx           # read-queue for console
  92         movl head(%edx),%ecx
  93 1:      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
 102 2:      movl %ecx,head(%edx)
 103         movl proc_list(%edx),%ecx
 104         testl %ecx,%ecx
 105         je 3f
 106         movl $0,(%ecx)
 107 3:      popl %edx
 108         popl %ecx
 109         ret
 110 
 111 ctrl:   movb $0x04,%al
 112         jmp 1f
 113 alt:    movb $0x10,%al
 114 1:      cmpb $0,e0
 115         je 2f
 116         addb %al,%al
 117 2:      orb %al,mode
 118         ret
 119 unctrl: movb $0x04,%al
 120         jmp 1f
 121 unalt:  movb $0x10,%al
 122 1:      cmpb $0,e0
 123         je 2f
 124         addb %al,%al
 125 2:      notb %al
 126         andb %al,mode
 127         ret
 128 
 129 lshift:
 130         orb $0x01,mode
 131         ret
 132 unlshift:
 133         andb $0xfe,mode
 134         ret
 135 rshift:
 136         orb $0x02,mode
 137         ret
 138 unrshift:
 139         andb $0xfd,mode
 140         ret
 141 
 142 caps:   testb $0x80,mode
 143         jne 1f
 144         xorb $4,leds
 145         xorb $0x40,mode
 146         orb $0x80,mode
 147 set_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
 155 uncaps: andb $0x7f,mode
 156         ret
 157 scroll:
 158         xorb $1,leds
 159         jmp set_leds
 160 num:    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  */
 167 cursor:
 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
 177 cur2:   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
 186 1:      ret
 187 
 188 cur:    movb cur_table(%eax),%al
 189         cmpb $'9,%al
 190         ja ok_cur
 191         movb $'~,%ah
 192 ok_cur: shll $16,%eax
 193         movw $0x5b1b,%ax
 194         xorl %ebx,%ebx
 195         jmp put_queue
 196 
 197 #if defined(KBD_FR)
 198 num_table:
 199         .ascii "789 456 1230."
 200 #else
 201 num_table:
 202         .ascii "789 456 1230,"
 203 #endif
 204 cur_table:
 205         .ascii "HA5 DGC YB623"
 206 
 207 /*
 208  * this routine handles function keys
 209  */
 210 func:
 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
 227 ok_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
 233 end_func:
 234         ret
 235 
 236 /*
 237  * function keys send F1:'esc [ [ A' F2:'esc [ [ B' etc.
 238  */
 239 func_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)
 245 key_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 
 261 shift_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 
 277 alt_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 
 295 key_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 
 312 shift_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 
 328 alt_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 
 346 key_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 
 363 shift_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 
 379 alt_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 
 398 key_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 
 414 shift_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 
 430 alt_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  */
 453 do_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
 461 1:      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
 471 2:      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
 478 3:      testb $0x10,mode                /* left alt */
 479         je 4f
 480         orb $0x80,%al
 481 4:      andl $0xff,%eax
 482         xorl %ebx,%ebx
 483         call put_queue
 484 none:   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  */
 491 minus:  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  */
 502 key_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  */
 572 kb_wait:
 573         pushl %eax
 574 1:      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  */
 583 reboot:
 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
 588 die:    jmp die

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