1/*	$NetBSD: cons_zskbd.c,v 1.3 2007/10/17 19:54:22 garbled Exp $	*/
2
3/*-
4 * Copyright (c) 2004, 2005 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by UCHIYAMA Yasushi.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#include <sys/param.h>
33#include <sys/systm.h>
34
35#include <lib/libsa/stand.h>
36#include <lib/libkern/libkern.h>
37
38#include <machine/sbd.h>
39
40#include "console.h"
41
42struct zskbd zskbd;
43
44int zskbd_common_getc(int);
45void zskbd_busy(void);
46
47static const uint8_t map_normal[] = {
48	'0',	'1',	'2',	'3',	'4',	'5',	'6',	'7',
49	'8',	'9',	'-',	'^',	'\\',	':',	'.',	'/',
50	'@',	'a',	'b',	'c',	'd',	'e',	'f',	'g',
51	'h',	'i',	'j',	'k',	'l',	'm',	'n',	'o',
52	'p',	'q',	'r',	's',	't',	'u',	'v',	'w',
53	'x',	'y',	'z',	'[',	',',	']',	';',	0x00,
54	'0',	'1',	'2',	'3',	'4',	'5',	'6',	'7',
55	'8',	'9',	' ',	',',	0x00,	0x00,	0x00,	0x00,
56	'\r',	'\r',	0x00,	0x00,	'\r',	0x00,	'-',	'.',
57	0xa3,	0xa2,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
58	0x08,	0x00,	0x0c,	0x7f,	0x12,	0x00,	0x00,	0x00,
59	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
60	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
61	0x00,	0x00,	0xa0,	0xa1,	0x00,	0x00,	0x00,	0x00,
62	'+',	'*',	'/',	0x1b,	0x01,	'=',	'\t',	0x00,
63	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
64};
65
66static const uint8_t map_shift[] = {
67	'0',	'!',	'\"',	'#',	'$',	'%',	'&',	'\'',
68	'(',	')',	'=',	'^',	'|',	'*',	'>',	'?',
69	'~',	'A',	'B',	'C',	'D',	'E',	'F',	'G',
70	'H',	'I',	'J',	'K',	'L',	'M',	'N',	'O',
71	'P',	'Q',	'R',	'S',	'T',	'U',	'V',	'W',
72	'X',	'Y',	'Z',	'{',	'<',	'}',	'+',	'_',
73	'0',	'1',	'2',	'3',	'4',	'5',	'6',	'7',
74	'8',	'9',	' ',	',',	0x00,	0x00,	0x00,	0x00,
75	'\r',	'\r',	'B',	'C',	'\r',	'E',	'-',	'.',
76	0xa3,	0xa2,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
77	0x08,	0x00,	0x0b,	0x7f,	0x12,	0x09,	0x00,	0x00,
78	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
79	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
80	0x00,	0x00,	0xa0,	0xa1,	0x00,	0x00,	0x00,	0x00,
81	'+',	'*',	'/',	0x1b,	0x01,	'=',	'\t',	0x00,
82	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
83};
84
85static const uint8_t map_ctrl[] = {
86	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
87	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
88	0xa4,	0x01,	0x02,	0x03,	0x04,	0x05,	0x06,	0x07,
89	0x08,	0x09,	0x0a,	0x0b,	0x0c,	0x0d,	0x0e,	0x0f,
90	0x10,	0x11,	0x12,	0x13,	0x14,	0x15,	0x16,	0x17,
91	0x18,	0x19,	0x1a,	0x1b,	0x1c,	0x1d,	0x1e,	0x1f,
92	'0',	'1',	'2',	'3',	'4',	'5',	'6',	'7',
93	'8',	'9',	' ',	',',	0x00,	0x00,	0x00,	0x00,
94	'\r',	'\r',	0x00,	0x00,	'\r',	0x00,	'-',	'.',
95	0xa3,	0xa2,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
96	0x08,	0x00,	0x00,	0x7f,	0x12,	0x00,	0x00,	0x00,
97	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
98	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
99	0x00,	0x00,	0xa0,	0xa1,	0x00,	0x00,	0x00,	0x00,
100	'+',	'*',	'/',	0x1b,	0x01,	'=',	'\t',	0x00,
101	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
102};
103
104static const uint8_t map_capslock[] = {
105	'0',	'1',	'2',	'3',	'4',	'5',	'6',	'7',
106	'8',	'9',	'-',	'^',	'\\',	':',	'.',	'/',
107	'@',	'A',	'B',	'C',	'D',	'E',	'F',	'G',
108	'H',	'I',	'J',	'K',	'L',	'M',	'N',	'O',
109	'P',	'Q',	'R',	'S',	'T',	'U',	'V',	'W',
110	'X',	'Y',	'Z',	'[',	',',	']',	';',	0x00,
111	'0',	'1',	'2',	'3',	'4',	'5',	'6',	'7',
112	'8',	'9',	' ',	',',	0x00,	0x00,	0x00,	0x00,
113	'\r',	'\r',	0x00,	0x00,	'\r',	0x00,	'-',	'.',
114	0xa3,	0xa2,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
115	0x08,	0x00,	0x0c,	0x7f,	0x12,	0x00,	0x00,	0x00,
116	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
117	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
118	0x00,	0x00,	0xa0,	0xa1,	0x00,	0x00,	0x00,	0x00,
119	'+',	'*',	'/',	0x1b,	0x01,	'=',	'\t',	0x00,
120	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
121};
122
123void
124zskbd_set_addr(uint32_t status, uint32_t data)
125{
126	zskbd.status = (volatile uint8_t *)status;
127	zskbd.data = (volatile uint8_t *)data;
128	zskbd.normal = map_normal;
129	zskbd.shift = map_shift;
130	zskbd.ctrl = map_ctrl;
131	zskbd.capslock = map_capslock;
132
133	cons.getc = zskbd_getc;
134	cons.scan = zskbd_scan;
135}
136
137void
138zskbd_print_keyscan(int on)
139{
140
141	zskbd.print = on;
142}
143
144int
145zskbd_getc(void)
146{
147
148	return zskbd_common_getc(0);
149}
150
151int
152zskbd_scan(void)
153{
154
155	return zskbd_common_getc(1);
156}
157
158int
159zskbd_common_getc(int scan)
160{
161#ifdef CHECK_KEY_RELEASE
162	static int released = 1;
163	int push;
164#endif
165	int v, c;
166
167	for (;;) {
168		if (scan) {
169			if ((*zskbd.status & 0x01) != 0x01)
170				return -1;
171		} else {
172			while ((*zskbd.status & 0x01) != 0x01)
173				continue;
174		}
175
176		v = *zskbd.data;
177		if (zskbd.print)
178			printf("scancode = 0x%x\n", v);
179
180		switch (v) {
181		case 123:	/* Shift-L */
182			/* FALLTHROUGH */
183		case 124:	/* Shift-R */
184			zskbd.keymap  |= 0x01;
185			break;
186		case 251:
187			/* FALLTHROUGH */
188		case 252:
189			zskbd.keymap &= ~0x01;
190			break;
191		case 120:	/* Ctrl-L */
192			zskbd.keymap |= 0x02;
193			break;
194		case 248:
195			zskbd.keymap &= ~0x02;
196			break;
197		case 121:	/* CapsLock */
198			if (zskbd.keymap & 0x04) {
199				zskbd.keymap  &= ~0x04;
200				zskbd_busy();
201				*zskbd.data = 0x90; /* LED */
202			} else {
203				zskbd.keymap  |= 0x04;
204				zskbd_busy();
205				*zskbd.data = 0x92; /* LED */
206			}
207			break;
208		default:
209#ifdef CHECK_KEY_RELEASE
210			push = (v & 0x80) == 0;
211			if (push && released) {
212				released = 0;
213				goto exit_loop;
214			}
215			if (!push)
216				released = 1;
217#else /* CHECK_KEY_RELEASE */
218			if ((v & 0x80) == 0)
219				goto exit_loop;
220#endif /* CHECK_KEY_RELEASE */
221			break;
222		}
223	}
224
225 exit_loop:
226	c = v & 0x7f;
227	if (zskbd.keymap & 0x01)	/* Shift */
228		return *(zskbd.shift + c);
229	if (zskbd.keymap & 0x02)	/* Ctrl */
230		return *(zskbd.ctrl + c);
231	if (zskbd.keymap & 0x04)	/* CapsLock */
232		return *(zskbd.capslock + c);
233				/* Normal */
234	return *(zskbd.normal + c);
235}
236
237void
238zskbd_busy(void)
239{
240
241#if 0 /* I misunderstand??? -uch */
242	do {
243		while ((*zskbd.status & 0x20) != 0x20)
244			;
245	} while ((*zskbd.status & 0x4) != 0x4);
246#endif
247}
248