root/kernel/chr_drv/keyboard.S~

/* [previous][next][first][last][top][bottom][index][help] */
/*
 *  linux/kernel/keyboard.S
 *
 *  (C) 1991  Linus Torvalds
 */

/*
 *      Thanks to Alfred Leung for US keyboard patches
 */

#include <linux/config.h>

.text
.globl _keyboard_interrupt

/*
 * these are for the keyboard read functions
 */
size    = 1024          /* must be a power of two ! And MUST be the same
                           as in tty_io.c !!!! */
head = 4
tail = 8
proc_list = 12
buf = 16

mode:   .byte 0         /* caps, alt, ctrl and shift mode */
leds:   .byte 2         /* num-lock, caps, scroll-lock mode (nom-lock on) */
e0:     .byte 0

/*
 *  con_int is the real interrupt routine that reads the
 *  keyboard scan-code and converts it into the appropriate
 *  ascii character(s).
 */
_keyboard_interrupt:
        pushl %eax
        pushl %ebx
        pushl %ecx
        pushl %edx
        push %ds
        push %es
        movl $0x10,%eax
        mov %ax,%ds
        mov %ax,%es
        xorl %al,%al            /* %eax is scan code */
        inb $0x60,%al
        cmpb $0xe0,%al
        je set_e0
        cmpb $0xe1,%al
        je set_e1
        call key_table(,%eax,4)
        movb $0,e0
e0_e1:  inb $0x61,%al
        jmp 1f
1:      jmp 1f
1:      orb $0x80,%al
        jmp 1f
1:      jmp 1f
1:      outb %al,$0x61
        jmp 1f
1:      jmp 1f
1:      andb $0x7F,%al
        outb %al,$0x61
        movb $0x20,%al
        outb %al,$0x20
        pushl $0
        call _do_tty_interrupt
        addl $4,%esp
        pop %es
        pop %ds
        popl %edx
        popl %ecx
        popl %ebx
        popl %eax
        iret
set_e0: movb $1,e0
        jmp e0_e1
set_e1: movb $2,e0
        jmp e0_e1

/*
 * This routine fills the buffer with max 8 bytes, taken from
 * %ebx:%eax. (%edx is high). The bytes are written in the
 * order %al,%ah,%eal,%eah,%bl,%bh ... until %eax is zero.
 */
put_queue:
        pushl %ecx
        pushl %edx
        movl _table_list,%edx           # read-queue for console
        movl head(%edx),%ecx
1:      movb %al,buf(%edx,%ecx)
        incl %ecx
        andl $size-1,%ecx
        cmpl tail(%edx),%ecx            # buffer full - discard everything
        je 3f
        shrdl $8,%ebx,%eax
        je 2f
        shrl $8,%ebx
        jmp 1b
2:      movl %ecx,head(%edx)
        movl proc_list(%edx),%ecx
        testl %ecx,%ecx
        je 3f
        movl $0,(%ecx)
3:      popl %edx
        popl %ecx
        ret

ctrl:   movb $0x04,%al
        jmp 1f
alt:    movb $0x10,%al
1:      cmpb $0,e0
        je 2f
        addb %al,%al
2:      orb %al,mode
        ret
unctrl: movb $0x04,%al
        jmp 1f
unalt:  movb $0x10,%al
1:      cmpb $0,e0
        je 2f
        addb %al,%al
2:      notb %al
        andb %al,mode
        ret

lshift:
        orb $0x01,mode
        ret
unlshift:
        andb $0xfe,mode
        ret
rshift:
        orb $0x02,mode
        ret
unrshift:
        andb $0xfd,mode
        ret

caps:   testb $0x80,mode
        jne 1f
        xorb $4,leds
        xorb $0x40,mode
        orb $0x80,mode
set_leds:
        call kb_wait
        movb $0xed,%al          /* set leds command */
        outb %al,$0x60
        call kb_wait
        movb leds,%al
        outb %al,$0x60
        ret
uncaps: andb $0x7f,mode
        ret
scroll:
        xorb $1,leds
        jmp set_leds
num:    xorb $2,leds
        jmp set_leds

/*
 *  curosr-key/numeric keypad cursor keys are handled here.
 *  checking for numeric keypad etc.
 */
cursor:
        subb $0x47,%al
        jb 1f
        cmpb $12,%al
        ja 1f
        jne cur2                /* check for ctrl-alt-del */
        testb $0x0c,mode
        je cur2
        testb $0x30,mode
        jne reboot
cur2:   cmpb $0x01,e0           /* e0 forces cursor movement */
        je cur
        testb $0x02,leds        /* not num-lock forces cursor */
        je cur
        testb $0x03,mode        /* shift forces cursor */
        jne cur
        xorl %ebx,%ebx
        movb num_table(%eax),%al
        jmp put_queue
1:      ret

cur:    movb cur_table(%eax),%al
        cmpb $'9,%al
        ja ok_cur
        movb $'~,%ah
ok_cur: shll $16,%eax
        movw $0x5b1b,%ax
        xorl %ebx,%ebx
        jmp put_queue

num_table:
        .ascii "789 456 1230,"
cur_table:
        .ascii "HA5 DGC YB623"

/*
 * this routine handles function keys
 */
func:
        pushl %eax
        pushl %ecx
        pushl %edx
        call _show_stat
        popl %edx
        popl %ecx
        popl %eax
        subb $0x3B,%al
        jb end_func
        cmpb $9,%al
        jbe ok_func
        subb $18,%al
        cmpb $10,%al
        jb end_func
        cmpb $11,%al
        ja end_func
ok_func:
        cmpl $4,%ecx            /* check that there is enough room */
        jl end_func
        movl func_table(,%eax,4),%eax
        xorl %ebx,%ebx
        jmp put_queue
end_func:
        ret

/*
 * function keys send F1:'esc [ [ A' F2:'esc [ [ B' etc.
 */
func_table:
        .long 0x415b5b1b,0x425b5b1b,0x435b5b1b,0x445b5b1b
        .long 0x455b5b1b,0x465b5b1b,0x475b5b1b,0x485b5b1b
        .long 0x495b5b1b,0x4a5b5b1b,0x4b5b5b1b,0x4c5b5b1b

#if     defined(KBD_FINNISH)
key_map:
        .byte 0,27
        .ascii "1234567890+'"
        .byte 127,9
        .ascii "qwertyuiop}"
        .byte 0,13,0
        .ascii "asdfghjkl|{"
        .byte 0,0
        .ascii "'zxcvbnm,.-"
        .byte 0,'*,0,32         /* 36-39 */
        .fill 16,1,0            /* 3A-49 */
        .byte '-,0,0,0,'+       /* 4A-4E */
        .byte 0,0,0,0,0,0,0     /* 4F-55 */
        .byte '<
        .fill 10,1,0

shift_map:
        .byte 0,27
        .ascii "!\"#$%&/()=?`"
        .byte 127,9
        .ascii "QWERTYUIOP]^"
        .byte 13,0
        .ascii "ASDFGHJKL\\["
        .byte 0,0
        .ascii "*ZXCVBNM;:_"
        .byte 0,'*,0,32         /* 36-39 */
        .fill 16,1,0            /* 3A-49 */
        .byte '-,0,0,0,'+       /* 4A-4E */
        .byte 0,0,0,0,0,0,0     /* 4F-55 */
        .byte '>
        .fill 10,1,0

alt_map:
        .byte 0,0
        .ascii "\0@\0$\0\0{[]}\\\0"
        .byte 0,0
        .byte 0,0,0,0,0,0,0,0,0,0,0
        .byte '~,13,0
        .byte 0,0,0,0,0,0,0,0,0,0,0
        .byte 0,0
        .byte 0,0,0,0,0,0,0,0,0,0,0
        .byte 0,0,0,0           /* 36-39 */
        .fill 16,1,0            /* 3A-49 */
        .byte 0,0,0,0,0         /* 4A-4E */
        .byte 0,0,0,0,0,0,0     /* 4F-55 */
        .byte '|
        .fill 10,1,0

#elif defined(KBD_US)

key_map:
        .byte 0,27
        .ascii "1234567890-="
        .byte 127,9
        .ascii "qwertyuiop[]"
        .byte 13,0
        .ascii "asdfghjkl;'"
        .byte '`,0
        .ascii "\\zxcvbnm,./"
        .byte 0,'*,0,32         /* 36-39 */
        .fill 16,1,0            /* 3A-49 */
        .byte '-,0,0,0,'+       /* 4A-4E */
        .byte 0,0,0,0,0,0,0     /* 4F-55 */
        .byte '<
        .fill 10,1,0


shift_map:
        .byte 0,27
        .ascii "!@#$%^&*()_+"
        .byte 127,9
        .ascii "QWERTYUIOP{}"
        .byte 13,0
        .ascii "ASDFGHJKL:\""
        .byte '~,0
        .ascii "|ZXCVBNM<>?"
        .byte 0,'*,0,32         /* 36-39 */
        .fill 16,1,0            /* 3A-49 */
        .byte '-,0,0,0,'+       /* 4A-4E */
        .byte 0,0,0,0,0,0,0     /* 4F-55 */
        .byte '>
        .fill 10,1,0

alt_map:
        .byte 0,0
        .ascii "\0@\0$\0\0{[]}\\\0"
        .byte 0,0
        .byte 0,0,0,0,0,0,0,0,0,0,0
        .byte '~,13,0
        .byte 0,0,0,0,0,0,0,0,0,0,0
        .byte 0,0
        .byte 0,0,0,0,0,0,0,0,0,0,0
        .byte 0,0,0,0           /* 36-39 */
        .fill 16,1,0            /* 3A-49 */
        .byte 0,0,0,0,0         /* 4A-4E */
        .byte 0,0,0,0,0,0,0     /* 4F-55 */
        .byte '|
        .fill 10,1,0

#else
#error "KBD-type not defined"
#endif
/*
 * do_self handles "normal" keys, ie keys that don't change meaning
 * and which have just one character returns.
 */
do_self:
        lea alt_map,%ebx
        testb $0x20,mode                /* alt-gr */
        jne 1f
        lea shift_map,%ebx
        testb $0x03,mode
        jne 1f
        lea key_map,%ebx
1:      movb (%ebx,%eax),%al
        orb %al,%al
        je none
        testb $0x4c,mode                /* ctrl or caps */
        je 2f
        cmpb $'a,%al
        jb 2f
        cmpb $'},%al
        ja 2f
        subb $32,%al
2:      testb $0x0c,mode                /* ctrl */
        je 3f
        cmpb $64,%al
        jb 3f
        cmpb $64+32,%al
        jae 3f
        subb $64,%al
3:      testb $0x10,mode                /* left alt */
        je 4f
        orb $0x80,%al
4:      andl $0xff,%eax
        xorl %ebx,%ebx
        call put_queue
none:   ret

/*
 * minus has a routine of it's own, as a 'E0h' before
 * the scan code for minus means that the numeric keypad
 * slash was pushed.
 */
minus:  cmpb $1,e0
        jne do_self
        movl $'/,%eax
        xorl %ebx,%ebx
        jmp put_queue
/*
 * do_space handles ctrl-space as an ASCII NUL.  Old habits die hard.
 */
do_space:
        testb $0x04,mode                /* ctrl */
        je do_self
        movl $0,%al                     /* ASCII NUL */
        xorl %ebx,%ebx
        jmp put_queue

/*
 * This table decides which routine to call when a scan-code has been
 * gotten. Most routines just call do_self, or none, depending if
 * they are make or break.
 */
key_table:
        .long none,do_self,do_self,do_self      /* 00-03 s0 esc 1 2 */
        .long do_self,do_self,do_self,do_self   /* 04-07 3 4 5 6 */
        .long do_self,do_self,do_self,do_self   /* 08-0B 7 8 9 0 */
        .long do_self,do_self,do_self,do_self   /* 0C-0F + ' bs tab */
        .long do_self,do_self,do_self,do_self   /* 10-13 q w e r */
        .long do_self,do_self,do_self,do_self   /* 14-17 t y u i */
        .long do_self,do_self,do_self,do_self   /* 18-1B o p } ^ */
        .long do_self,ctrl,do_self,do_self      /* 1C-1F enter ctrl a s */
        .long do_self,do_self,do_self,do_self   /* 20-23 d f g h */
        .long do_self,do_self,do_self,do_self   /* 24-27 j k l | */
        .long do_self,do_self,lshift,do_self    /* 28-2B { para lshift , */
        .long do_self,do_self,do_self,do_self   /* 2C-2F z x c v */
        .long do_self,do_self,do_self,do_self   /* 30-33 b n m , */
        .long do_self,minus,rshift,do_self      /* 34-37 . - rshift * */
        .long alt,do_space,ctrl,func            /* 38-3B alt sp caps f1 */
        .long func,func,func,func               /* 3C-3F f2 f3 f4 f5 */
        .long func,func,func,func               /* 40-43 f6 f7 f8 f9 */
        .long func,num,scroll,cursor            /* 44-47 f10 num scr home */
        .long cursor,cursor,do_self,cursor      /* 48-4B up pgup - left */
        .long cursor,cursor,do_self,cursor      /* 4C-4F n5 right + end */
        .long cursor,cursor,cursor,cursor       /* 50-53 dn pgdn ins del */
        .long none,none,do_self,func            /* 54-57 sysreq ? < f11 */
        .long func,none,none,none               /* 58-5B f12 ? ? ? */
        .long none,none,none,none               /* 5C-5F ? ? ? ? */
        .long none,none,none,none               /* 60-63 ? ? ? ? */
        .long none,none,none,none               /* 64-67 ? ? ? ? */
        .long none,none,none,none               /* 68-6B ? ? ? ? */
        .long none,none,none,none               /* 6C-6F ? ? ? ? */
        .long none,none,none,none               /* 70-73 ? ? ? ? */
        .long none,none,none,none               /* 74-77 ? ? ? ? */
        .long none,none,none,none               /* 78-7B ? ? ? ? */
        .long none,none,none,none               /* 7C-7F ? ? ? ? */
        .long none,none,none,none               /* 80-83 ? br br br */
        .long none,none,none,none               /* 84-87 br br br br */
        .long none,none,none,none               /* 88-8B br br br br */
        .long none,none,none,none               /* 8C-8F br br br br */
        .long none,none,none,none               /* 90-93 br br br br */
        .long none,none,none,none               /* 94-97 br br br br */
        .long none,none,none,none               /* 98-9B br br br br */
        .long none,unctrl,none,none             /* 9C-9F br unctrl br br */
        .long none,none,none,none               /* A0-A3 br br br br */
        .long none,none,none,none               /* A4-A7 br br br br */
        .long none,none,unlshift,none           /* A8-AB br br unlshift br */
        .long none,none,none,none               /* AC-AF br br br br */
        .long none,none,none,none               /* B0-B3 br br br br */
        .long none,none,unrshift,none           /* B4-B7 br br unrshift br */
        .long unalt,none,unctrl,none            /* B8-BB unalt br uncaps br */
        .long none,none,none,none               /* BC-BF br br br br */
        .long none,none,none,none               /* C0-C3 br br br br */
        .long none,none,none,none               /* C4-C7 br br br br */
        .long none,none,none,none               /* C8-CB br br br br */
        .long none,none,none,none               /* CC-CF br br br br */
        .long none,none,none,none               /* D0-D3 br br br br */
        .long none,none,none,none               /* D4-D7 br br br br */
        .long none,none,none,none               /* D8-DB br ? ? ? */
        .long none,none,none,none               /* DC-DF ? ? ? ? */
        .long none,none,none,none               /* E0-E3 e0 e1 ? ? */
        .long none,none,none,none               /* E4-E7 ? ? ? ? */
        .long none,none,none,none               /* E8-EB ? ? ? ? */
        .long none,none,none,none               /* EC-EF ? ? ? ? */
        .long none,none,none,none               /* F0-F3 ? ? ? ? */
        .long none,none,none,none               /* F4-F7 ? ? ? ? */
        .long none,none,none,none               /* F8-FB ? ? ? ? */
        .long none,none,none,none               /* FC-FF ? ? ? ? */

/*
 * kb_wait waits for the keyboard controller buffer to empty.
 * there is no timeout - if the buffer doesn't empty, we hang.
 */
kb_wait:
        pushl %eax
1:      inb $0x64,%al
        testb $0x02,%al
        jne 1b
        popl %eax
        ret
/*
 * This routine reboots the machine by asking the keyboard
 * controller to pulse the reset-line low.
 */
reboot:
        call kb_wait
        movw $0x1234,0x472      /* don't do memory check */
        movb $0xfc,%al          /* pulse reset and A20 low */
        outb %al,$0x64
die:    jmp die

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