[BACK]Return to kbd.c CVS log [TXT][DIR] Up to [local] / prex / dev / i386 / pc

Annotation of prex/dev/i386/pc/kbd.c, Revision 1.1

1.1     ! nbrk        1: /*-
        !             2:  * Copyright (c) 2005, Kohsuke Ohtani
        !             3:  * All rights reserved.
        !             4:  *
        !             5:  * Redistribution and use in source and binary forms, with or without
        !             6:  * modification, are permitted provided that the following conditions
        !             7:  * are met:
        !             8:  * 1. Redistributions of source code must retain the above copyright
        !             9:  *    notice, this list of conditions and the following disclaimer.
        !            10:  * 2. Redistributions in binary form must reproduce the above copyright
        !            11:  *    notice, this list of conditions and the following disclaimer in the
        !            12:  *    documentation and/or other materials provided with the distribution.
        !            13:  * 3. Neither the name of the author nor the names of any co-contributors
        !            14:  *    may be used to endorse or promote products derived from this software
        !            15:  *    without specific prior written permission.
        !            16:  *
        !            17:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
        !            18:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            19:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            20:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
        !            21:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            22:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            23:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            24:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            25:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            26:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            27:  * SUCH DAMAGE.
        !            28:  */
        !            29:
        !            30: /*
        !            31:  * kbd.c - keyboard driver for PC
        !            32:  */
        !            33:
        !            34: #include <driver.h>
        !            35: #include <prex/keycode.h>
        !            36: #include <sys/tty.h>
        !            37: #include <cpufunc.h>
        !            38: #include <pm.h>
        !            39: #include <console.h>
        !            40: #include "kmc.h"
        !            41:
        !            42: /* Parameters */
        !            43: #define KBD_IRQ                1
        !            44:
        !            45: static int kbd_init(void);
        !            46:
        !            47: /*
        !            48:  * Driver structure
        !            49:  */
        !            50: struct driver kbd_drv = {
        !            51:        /* name */      "PC/AT Keyboard",
        !            52:        /* order */     8,
        !            53:        /* init */      kbd_init,
        !            54: };
        !            55:
        !            56: /*
        !            57:  * Device I/O table
        !            58:  */
        !            59: static struct devio kbd_io = {
        !            60:        /* open */      NULL,
        !            61:        /* close */     NULL,
        !            62:        /* read */      NULL,
        !            63:        /* write */     NULL,
        !            64:        /* ioctl */     NULL,
        !            65:        /* event */     NULL,
        !            66: };
        !            67:
        !            68: /*
        !            69:  * Key map
        !            70:  */
        !            71: static const u_char key_map[] = {
        !            72:        0,      0x1b,   '1',    '2',    '3',    '4',    '5',    '6',
        !            73:        '7',    '8',    '9',    '0',    '-',    '=',    '\b',   '\t',
        !            74:        'q',    'w',    'e',    'r',    't',    'y',    'u',    'i',
        !            75:        'o',    'p',    '[',    ']',    '\n',   K_CTRL, 'a',    's',
        !            76:        'd',    'f',    'g',    'h',    'j',    'k',    'l',    ';',
        !            77:        '\'',   '`',    K_SHFT, '\\',   'z',    'x',    'c',    'v',
        !            78:        'b',    'n',    'm',    ',',    '.',    '/',    K_SHFT, '*',
        !            79:        K_ALT,  ' ',    K_CAPS, K_F1,   K_F2,   K_F3,   K_F4,   K_F5,
        !            80:        K_F6,   K_F7,   K_F8,   K_F9,   K_F10,  0,      0,      K_HOME,
        !            81:        K_UP,   K_PGUP, 0,      K_LEFT, 0,      K_RGHT, 0,      K_END,
        !            82:        K_DOWN, K_PGDN, K_INS,  0x7f,   K_F11,  K_F12
        !            83: };
        !            84:
        !            85: #define KEY_MAX (sizeof(key_map) / sizeof(char))
        !            86:
        !            87: static const u_char shift_map[] = {
        !            88:        0,      0x1b,   '!',    '@',    '#',    '$',    '%',    '^',
        !            89:        '&',    '*',    '(',    ')',    '_',    '+',    '\b',   '\t',
        !            90:        'Q',    'W',    'E',    'R',    'T',    'Y',    'U',    'I',
        !            91:        'O',    'P',    '{',    '}',    '\n',   K_CTRL, 'A',    'S',
        !            92:        'D',    'F',    'G',    'H',    'J',    'K',    'L',    ':',
        !            93:        '"',    '~',    0,      '|',    'Z',    'X',    'C',    'V',
        !            94:        'B',    'N',    'M',    '<',    '>',    '?',    0,      '*',
        !            95:        K_ALT,  ' ',    0,      0,      0,      0,      0,      0,
        !            96:        0,      0,      0,      0,      0,      0,      0,      K_HOME,
        !            97:        K_UP,   K_PGUP, 0,      K_LEFT, 0,      K_RGHT, 0,      K_END,
        !            98:        K_DOWN, K_PGDN, K_INS,  0x7f,   0,      0
        !            99: };
        !           100:
        !           101: static device_t kbd_dev;       /* Device object */
        !           102: static irq_t kbd_irq;          /* Handle for keyboard irq */
        !           103: static struct tty *tty;
        !           104:
        !           105: static int shift;
        !           106: static int alt;
        !           107: static int ctrl;
        !           108: static int capslk;
        !           109:
        !           110: static int led_sts;
        !           111:
        !           112:
        !           113: /*
        !           114:  * Send command to keyboard controller
        !           115:  */
        !           116: static void
        !           117: kbd_cmd(u_char cmd)
        !           118: {
        !           119:
        !           120:        wait_ibe();
        !           121:        outb(cmd, KMC_CMD);
        !           122: }
        !           123:
        !           124:
        !           125: /*
        !           126:  * Update LEDs for current modifier state.
        !           127:  */
        !           128: static void
        !           129: kbd_setleds(void)
        !           130: {
        !           131:
        !           132:        outb(0xed, KMC_DATA);
        !           133:        while (inb(KMC_STS) & 2);
        !           134:        outb(led_sts, KMC_DATA);
        !           135:        while (inb(KMC_STS) & 2);
        !           136: }
        !           137:
        !           138: #ifdef DEBUG
        !           139: /*
        !           140:  * Help for keyboard debug function
        !           141:  */
        !           142: static void
        !           143: kbd_dump_help(void)
        !           144: {
        !           145:
        !           146:        printf("\nSystem dump usage:\n");
        !           147:        printf("F1=help F2=thread F3=task F4=mem\n");
        !           148: }
        !           149: #endif
        !           150:
        !           151:
        !           152: /*
        !           153:  * Interrupt service routine
        !           154:  */
        !           155: static int
        !           156: kbd_isr(int irq)
        !           157: {
        !           158:        u_char sc, ac;          /* scan & ascii code */
        !           159:        u_char val;
        !           160:        int press;
        !           161:
        !           162:        /* Get scan code */
        !           163:        wait_obf();
        !           164:        sc = inb(KMC_DATA);
        !           165:
        !           166:        /* Send ack to the controller */
        !           167:        val = inb(KMC_PORTB);
        !           168:        outb(val | 0x80, KMC_PORTB);
        !           169:        outb(val, KMC_PORTB);
        !           170:
        !           171:        /* Convert scan code to ascii */
        !           172:        press = sc & 0x80 ? 0 : 1;
        !           173:        sc = sc & 0x7f;
        !           174:        if (sc >= KEY_MAX)
        !           175:                return 0;
        !           176:        ac = key_map[sc];
        !           177:
        !           178: #ifdef CONFIG_PM
        !           179:        /* Reload power management timer */
        !           180:        if (press)
        !           181:                pm_active();
        !           182: #endif
        !           183:
        !           184:        /* Check meta key */
        !           185:        switch (ac) {
        !           186:        case K_SHFT:
        !           187:                shift = press;
        !           188:                return 0;
        !           189:        case K_CTRL:
        !           190:                ctrl = press;
        !           191:                return 0;
        !           192:        case K_ALT:
        !           193:                alt = press;
        !           194:                return 0;
        !           195:        case K_CAPS:
        !           196:                capslk = !capslk;
        !           197:                return INT_CONTINUE;
        !           198:        }
        !           199:
        !           200:        /* Ignore key release */
        !           201:        if (!press)
        !           202:                return 0;
        !           203:
        !           204: #ifdef DEBUG
        !           205:        if (ac == K_F1) {
        !           206:                kbd_dump_help();
        !           207:                return 0;
        !           208:        }
        !           209:        if (ac >= K_F2 && ac <= K_F12) {
        !           210:                debug_dump(ac - K_F1);
        !           211:                return 0;
        !           212:        }
        !           213: #endif
        !           214:        if (ac >= 0x80) {
        !           215:                tty_input(ac, tty);
        !           216:                return 0;
        !           217:        }
        !           218:
        !           219:        /* Check Alt+Ctrl+Del */
        !           220:        if (alt && ctrl && ac == 0x7f) {
        !           221:                machine_reset();
        !           222:        }
        !           223:
        !           224:        /* Check ctrl & shift state */
        !           225:        if (ctrl) {
        !           226:                if (ac >= 'a' && ac <= 'z')
        !           227:                        ac = ac - 'a' + 0x01;
        !           228:                else if (ac == '\\')
        !           229:                        ac = 0x1c;
        !           230:                else
        !           231:                        ac = 0;
        !           232:        } else if (shift)
        !           233:                ac = shift_map[sc];
        !           234:
        !           235:        if (ac == 0)
        !           236:                return 0;
        !           237:
        !           238:        /* Check caps lock state */
        !           239:        if (capslk) {
        !           240:                if (ac >= 'A' && ac <= 'Z')
        !           241:                        ac += 'a' - 'A';
        !           242:                else if (ac >= 'a' && ac <= 'z')
        !           243:                        ac -= 'a' - 'A';
        !           244:        }
        !           245:
        !           246:        /* Check alt key */
        !           247:        if (alt)
        !           248:                ac |= 0x80;
        !           249:
        !           250:        /* Insert key to queue */
        !           251:        tty_input(ac, tty);
        !           252:        return 0;
        !           253: }
        !           254:
        !           255: /*
        !           256:  * Interrupt service thread
        !           257:  */
        !           258: static void
        !           259: kbd_ist(int irq)
        !           260: {
        !           261:        int val = 0;
        !           262:
        !           263:        /* Update LEDs */
        !           264:        if (capslk)
        !           265:                val |= 0x04;
        !           266:        if (led_sts != val) {
        !           267:                led_sts = val;
        !           268:                kbd_setleds();
        !           269:        }
        !           270:        return;
        !           271: }
        !           272:
        !           273: int
        !           274: kbd_init(void)
        !           275: {
        !           276:
        !           277:        kbd_dev = device_create(&kbd_io, "kbd", DF_CHR);
        !           278:        ASSERT(kbd_dev);
        !           279:
        !           280:        /* Disable keyboard controller */
        !           281:        kbd_cmd(CMD_KBD_DIS);
        !           282:
        !           283:        led_sts = 0;
        !           284:        /* kbd_setleds(); */
        !           285:
        !           286:        kbd_irq = irq_attach(KBD_IRQ, IPL_INPUT, 0, kbd_isr, kbd_ist);
        !           287:        ASSERT(kbd_irq != IRQ_NULL);
        !           288:
        !           289:        /* Discard garbage data */
        !           290:        while (inb(KMC_STS) & STS_OBF)
        !           291:                inb(KMC_DATA);
        !           292:
        !           293:        /* Enable keyboard controller */
        !           294:        kbd_cmd(CMD_KBD_EN);
        !           295:
        !           296:        console_attach(&tty);
        !           297:        return 0;
        !           298: }

CVSweb