root/sys/arch/ews4800mips/stand/common/cons_zskbd.c
/*      $NetBSD: cons_zskbd.c,v 1.4 2008/04/28 20:23:18 martin Exp $    */

/*-
 * Copyright (c) 2004, 2005 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by UCHIYAMA Yasushi.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include <sys/param.h>
#include <sys/systm.h>

#include <lib/libsa/stand.h>
#include <lib/libkern/libkern.h>

#include <machine/sbd.h>

#include "console.h"

struct zskbd zskbd;

int zskbd_common_getc(int);
void zskbd_busy(void);

static const uint8_t map_normal[] = {
        '0',    '1',    '2',    '3',    '4',    '5',    '6',    '7',
        '8',    '9',    '-',    '^',    '\\',   ':',    '.',    '/',
        '@',    'a',    'b',    'c',    'd',    'e',    'f',    'g',
        'h',    'i',    'j',    'k',    'l',    'm',    'n',    'o',
        'p',    'q',    'r',    's',    't',    'u',    'v',    'w',
        'x',    'y',    'z',    '[',    ',',    ']',    ';',    0x00,
        '0',    '1',    '2',    '3',    '4',    '5',    '6',    '7',
        '8',    '9',    ' ',    ',',    0x00,   0x00,   0x00,   0x00,
        '\r',   '\r',   0x00,   0x00,   '\r',   0x00,   '-',    '.',
        0xa3,   0xa2,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,
        0x08,   0x00,   0x0c,   0x7f,   0x12,   0x00,   0x00,   0x00,
        0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,
        0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,
        0x00,   0x00,   0xa0,   0xa1,   0x00,   0x00,   0x00,   0x00,
        '+',    '*',    '/',    0x1b,   0x01,   '=',    '\t',   0x00,
        0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,
};

static const uint8_t map_shift[] = {
        '0',    '!',    '\"',   '#',    '$',    '%',    '&',    '\'',
        '(',    ')',    '=',    '^',    '|',    '*',    '>',    '?',
        '~',    'A',    'B',    'C',    'D',    'E',    'F',    'G',
        'H',    'I',    'J',    'K',    'L',    'M',    'N',    'O',
        'P',    'Q',    'R',    'S',    'T',    'U',    'V',    'W',
        'X',    'Y',    'Z',    '{',    '<',    '}',    '+',    '_',
        '0',    '1',    '2',    '3',    '4',    '5',    '6',    '7',
        '8',    '9',    ' ',    ',',    0x00,   0x00,   0x00,   0x00,
        '\r',   '\r',   'B',    'C',    '\r',   'E',    '-',    '.',
        0xa3,   0xa2,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,
        0x08,   0x00,   0x0b,   0x7f,   0x12,   0x09,   0x00,   0x00,
        0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,
        0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,
        0x00,   0x00,   0xa0,   0xa1,   0x00,   0x00,   0x00,   0x00,
        '+',    '*',    '/',    0x1b,   0x01,   '=',    '\t',   0x00,
        0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,
};

static const uint8_t map_ctrl[] = {
        0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,
        0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,
        0xa4,   0x01,   0x02,   0x03,   0x04,   0x05,   0x06,   0x07,
        0x08,   0x09,   0x0a,   0x0b,   0x0c,   0x0d,   0x0e,   0x0f,
        0x10,   0x11,   0x12,   0x13,   0x14,   0x15,   0x16,   0x17,
        0x18,   0x19,   0x1a,   0x1b,   0x1c,   0x1d,   0x1e,   0x1f,
        '0',    '1',    '2',    '3',    '4',    '5',    '6',    '7',
        '8',    '9',    ' ',    ',',    0x00,   0x00,   0x00,   0x00,
        '\r',   '\r',   0x00,   0x00,   '\r',   0x00,   '-',    '.',
        0xa3,   0xa2,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,
        0x08,   0x00,   0x00,   0x7f,   0x12,   0x00,   0x00,   0x00,
        0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,
        0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,
        0x00,   0x00,   0xa0,   0xa1,   0x00,   0x00,   0x00,   0x00,
        '+',    '*',    '/',    0x1b,   0x01,   '=',    '\t',   0x00,
        0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,
};

static const uint8_t map_capslock[] = {
        '0',    '1',    '2',    '3',    '4',    '5',    '6',    '7',
        '8',    '9',    '-',    '^',    '\\',   ':',    '.',    '/',
        '@',    'A',    'B',    'C',    'D',    'E',    'F',    'G',
        'H',    'I',    'J',    'K',    'L',    'M',    'N',    'O',
        'P',    'Q',    'R',    'S',    'T',    'U',    'V',    'W',
        'X',    'Y',    'Z',    '[',    ',',    ']',    ';',    0x00,
        '0',    '1',    '2',    '3',    '4',    '5',    '6',    '7',
        '8',    '9',    ' ',    ',',    0x00,   0x00,   0x00,   0x00,
        '\r',   '\r',   0x00,   0x00,   '\r',   0x00,   '-',    '.',
        0xa3,   0xa2,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,
        0x08,   0x00,   0x0c,   0x7f,   0x12,   0x00,   0x00,   0x00,
        0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,
        0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,
        0x00,   0x00,   0xa0,   0xa1,   0x00,   0x00,   0x00,   0x00,
        '+',    '*',    '/',    0x1b,   0x01,   '=',    '\t',   0x00,
        0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,
};

void
zskbd_set_addr(uint32_t status, uint32_t data)
{
        zskbd.status = (volatile uint8_t *)status;
        zskbd.data = (volatile uint8_t *)data;
        zskbd.normal = map_normal;
        zskbd.shift = map_shift;
        zskbd.ctrl = map_ctrl;
        zskbd.capslock = map_capslock;

        cons.getc = zskbd_getc;
        cons.scan = zskbd_scan;
}

void
zskbd_print_keyscan(int on)
{

        zskbd.print = on;
}

int
zskbd_getc(void)
{

        return zskbd_common_getc(0);
}

int
zskbd_scan(void)
{

        return zskbd_common_getc(1);
}

int
zskbd_common_getc(int scan)
{
#ifdef CHECK_KEY_RELEASE
        static int released = 1;
        int push;
#endif
        int v, c;

        for (;;) {
                if (scan) {
                        if ((*zskbd.status & 0x01) != 0x01)
                                return -1;
                } else {
                        while ((*zskbd.status & 0x01) != 0x01)
                                continue;
                }

                v = *zskbd.data;
                if (zskbd.print)
                        printf("scancode = 0x%x\n", v);

                switch (v) {
                case 123:       /* Shift-L */
                        /* FALLTHROUGH */
                case 124:       /* Shift-R */
                        zskbd.keymap  |= 0x01;
                        break;
                case 251:
                        /* FALLTHROUGH */
                case 252:
                        zskbd.keymap &= ~0x01;
                        break;
                case 120:       /* Ctrl-L */
                        zskbd.keymap |= 0x02;
                        break;
                case 248:
                        zskbd.keymap &= ~0x02;
                        break;
                case 121:       /* CapsLock */
                        if (zskbd.keymap & 0x04) {
                                zskbd.keymap  &= ~0x04;
                                zskbd_busy();
                                *zskbd.data = 0x90; /* LED */
                        } else {
                                zskbd.keymap  |= 0x04;
                                zskbd_busy();
                                *zskbd.data = 0x92; /* LED */
                        }
                        break;
                default:
#ifdef CHECK_KEY_RELEASE
                        push = (v & 0x80) == 0;
                        if (push && released) {
                                released = 0;
                                goto exit_loop;
                        }
                        if (!push)
                                released = 1;
#else /* CHECK_KEY_RELEASE */
                        if ((v & 0x80) == 0)
                                goto exit_loop;
#endif /* CHECK_KEY_RELEASE */
                        break;
                }
        }

 exit_loop:
        c = v & 0x7f;
        if (zskbd.keymap & 0x01)        /* Shift */
                return *(zskbd.shift + c);
        if (zskbd.keymap & 0x02)        /* Ctrl */
                return *(zskbd.ctrl + c);
        if (zskbd.keymap & 0x04)        /* CapsLock */
                return *(zskbd.capslock + c);
                                /* Normal */
        return *(zskbd.normal + c);
}

void
zskbd_busy(void)
{

#if 0 /* I misunderstand??? -uch */
        do {
                while ((*zskbd.status & 0x20) != 0x20)
                        ;
        } while ((*zskbd.status & 0x4) != 0x4);
#endif
}