1 /*	$NetBSD: cons_zskbd.c,v 1.4 2008/04/28 20:23:18 martin 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 
42 struct zskbd zskbd;
43 
44 int zskbd_common_getc(int);
45 void zskbd_busy(void);
46 
47 static 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 
66 static 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 
85 static 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 
104 static 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 
123 void
124 zskbd_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 
137 void
138 zskbd_print_keyscan(int on)
139 {
140 
141 	zskbd.print = on;
142 }
143 
144 int
145 zskbd_getc(void)
146 {
147 
148 	return zskbd_common_getc(0);
149 }
150 
151 int
152 zskbd_scan(void)
153 {
154 
155 	return zskbd_common_getc(1);
156 }
157 
158 int
159 zskbd_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 
237 void
238 zskbd_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