/* $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
}