vrkiu.c revision 1.22 1 /* $NetBSD: vrkiu.c,v 1.22 2000/06/03 08:00:44 takemura Exp $ */
2
3 /*-
4 * Copyright (c) 1999 SASAKI Takesi All rights reserved.
5 * Copyright (c) 1999 TAKEMRUA, Shin All rights reserved.
6 * Copyright (c) 1999 PocketBSD Project. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the PocketBSD project
19 * and its contributors.
20 * 4. Neither the name of the project nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 */
37
38 #include <sys/param.h>
39 #include <sys/tty.h>
40 #include <sys/systm.h>
41 #include <sys/device.h>
42 #include <sys/conf.h>
43 #include <sys/kernel.h>
44 #include <sys/proc.h>
45
46 #include <machine/intr.h>
47 #include <machine/cpu.h>
48 #include <machine/bus.h>
49 #include <machine/platid.h>
50 #include <machine/platid_mask.h>
51
52 #include <hpcmips/vr/vr.h>
53 #include <hpcmips/vr/vripvar.h>
54 #include <hpcmips/vr/vrkiuvar.h>
55 #include <hpcmips/vr/vrkiureg.h>
56 #include <hpcmips/vr/icureg.h>
57
58 #include "opt_wsdisplay_compat.h"
59 #include "opt_pckbd_layout.h"
60 #include <dev/wscons/wsconsio.h>
61 #include <dev/wscons/wskbdvar.h>
62 #include <dev/wscons/wsksymdef.h>
63 #include <dev/wscons/wsksymvar.h>
64 #include <dev/pckbc/wskbdmap_mfii.h>
65 #ifdef WSDISPLAY_COMPAT_RAWKBD
66 #include <hpcmips/dev/pckbd_encode.h>
67 #endif
68
69 #define VRKIUDEBUG
70 #ifdef VRKIUDEBUG
71 int vrkiu_debug = 0;
72 #define DPRINTF(arg) if (vrkiu_debug) printf arg;
73 #else
74 #define DPRINTF(arg)
75 #endif
76
77 /*
78 * structure and data types
79 */
80 struct vrkiu_chip {
81 bus_space_tag_t kc_iot;
82 bus_space_handle_t kc_ioh;
83 unsigned short kc_scandata[KIU_NSCANLINE/2];
84 int kc_polling;
85 #define NEVENTQ 32
86 struct {
87 u_int kc_type;
88 int kc_data;
89 } kc_eventq[NEVENTQ], *kc_head, *kc_tail;
90 int kc_nevents;
91
92 struct vrkiu_softc* kc_sc; /* back link */
93 };
94
95 struct vrkiu_softc {
96 struct device sc_dev;
97 struct vrkiu_chip *sc_chip;
98 struct vrkiu_chip sc_chip_body;
99 int sc_enabled;
100 struct device *sc_wskbddev;
101 #ifdef WSDISPLAY_COMPAT_RAWKBD
102 int sc_rawkbd;
103 #endif
104
105 void *sc_handler;
106 };
107
108 /*
109 * function prototypes
110 */
111 static int vrkiumatch __P((struct device *, struct cfdata *, void *));
112 static void vrkiuattach __P((struct device *, struct device *, void *));
113
114 int vrkiu_intr __P((void *));
115
116 static int vrkiu_init(struct vrkiu_chip*, bus_space_tag_t, bus_space_handle_t);
117 static void vrkiu_write __P((struct vrkiu_chip *, int, unsigned short));
118 static unsigned short vrkiu_read __P((struct vrkiu_chip *, int));
119 static int vrkiu_is_console(bus_space_tag_t, bus_space_handle_t);
120 static int detect_key __P((struct vrkiu_chip *));
121 static int vrkiu_getevent __P((struct vrkiu_chip*, u_int*, int*));
122 static int vrkiu_putevent __P((struct vrkiu_chip*, u_int, int));
123
124 /* wskbd accessopts */
125 int vrkiu_enable __P((void *, int));
126 void vrkiu_set_leds __P((void *, int));
127 int vrkiu_ioctl __P((void *, u_long, caddr_t, int, struct proc *));
128
129 /* consopts */
130 void vrkiu_cngetc __P((void*, u_int*, int*));
131 void vrkiu_cnpollc __P((void *, int));
132
133 /*
134 * global/static data
135 */
136 struct cfattach vrkiu_ca = {
137 sizeof(struct vrkiu_softc), vrkiumatch, vrkiuattach
138 };
139
140 const struct wskbd_accessops vrkiu_accessops = {
141 vrkiu_enable,
142 vrkiu_set_leds,
143 vrkiu_ioctl,
144 };
145
146 const struct wskbd_consops vrkiu_consops = {
147 vrkiu_cngetc,
148 vrkiu_cnpollc,
149 };
150
151 struct wskbd_mapdata vrkiu_keymapdata = {
152 pckbd_keydesctab,
153 #ifdef PCKBD_LAYOUT
154 PCKBD_LAYOUT,
155 #else
156 KB_US,
157 #endif
158 };
159
160 struct vrkiu_chip *vrkiu_consdata = NULL;
161
162 #define UNK -1 /* unknown */
163 #define IGN -2 /* ignore */
164
165 static char default_keytrans[] = {
166 /*00*/ UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK, /* - - - - - - - - */
167 /*08*/ UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK, /* - - - - - - - - */
168 /*10*/ UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK, /* - - - - - - - - */
169 /*18*/ UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK, /* - - - - - - - - */
170 /*20*/ UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK, /* - - - - - - - - */
171 /*28*/ UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK, /* - - - - - - - - */
172 /*30*/ UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK, /* - - - - - - - - */
173 /*38*/ UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK, /* - - - - - - - - */
174 /*40*/ UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK, /* - - - - - - - - */
175 /*48*/ UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK, /* - - - - - - - - */
176 /*50*/ UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK, /* - - - - - - - - */
177 /*58*/ UNK, UNK, UNK, UNK, UNK, UNK, UNK, UNK, /* - - - - - - - - */
178 };
179
180 /* NEC MobileGearII MCR series (Japan) */
181 static char mcr_jp_keytrans[] = {
182 /*00*/ 77, 28, 25, 52, 21, 48, 44, 57, /* right ent p . y b z space */
183 /*08*/ 80, 53, 24, 51, 20, 47, 30, 123, /* down / o , t v a nfer */
184 /*10*/ 75, 115, 23, 50, 19, 46, 17, 221, /* left \ i m r c w menu */
185 /*18*/ 13, IGN, 22, IGN, 18, 45, 16, 2, /* ^ - u - e x q 1 */
186 /*20*/ 81, 41, 11, 38, 40, 34, 15, 59, /* pgdn h/z 0 l : g tab f1 */
187 /*28*/ 121, 39, 10, 49, 6, 33, 3, 37, /* xfer ; 9 n 5 f 2 k */
188 /*30*/ 72, 27, 9, 36, 5, 32, 7, IGN, /* up [ 8 j 4 d 6 - */
189 /*38*/ 12, 26, 8, 35, 4, 43, 31, IGN, /* - @ 7 h 3 ] s - */
190 /*40*/ 58, IGN, IGN, IGN, 14, IGN, 66, 61, /* caps - - - bs - f8 f3 */
191 /*48*/ IGN, 56, IGN, IGN, 125, 112, 65, 62, /* - alt - - | k/h f7 f4 */
192 /*50*/ IGN, IGN, 29, IGN, 68, 73, 64, 60, /* - - ctrl - f10 pgup f6 f2 */
193 /*58*/ IGN, IGN, IGN, 42, 14, 67, 63, 1, /* - - - shift del f9 f5 esc */
194 };
195
196 /* IBM WorkPad z50 */
197 static char z50_keytrans[] = {
198 /*00*/ 59, 61, 63, 65, 67, IGN, IGN, 87, /* f1 f3 f5 f7 f9 - - f11 */
199 /*08*/ 60, 62, 64, 66, 68, IGN, IGN, 88, /* f2 f4 f6 f8 f10 - - f12 */
200 /*10*/ 40, 26, 12, 11, 25, 39, 72, 53, /* ' [ - 0 p ; up / */
201 /*18*/ IGN, IGN, IGN, 10, 24, 38, 52, IGN, /* - - - 9 o l . - */
202 /*20*/ 75, 27, 13, 9, 23, 37, 51, IGN, /* left ] = 8 i k , - */
203 /*28*/ 35, 21, 7, 8, 22, 36, 50, 49, /* h y 6 7 u j m n */
204 /*30*/ IGN, 14, 69, 14, IGN, 43, 28, 57, /* - bs num del - \ ent sp */
205 /*38*/ 34, 20, 6, 5, 19, 33, 47, 48, /* g t 5 4 r f v b */
206 /*40*/ IGN, IGN, IGN, 4, 18, 32, 46, 77, /* - - - 3 e d c right */
207 /*48*/ IGN, IGN, IGN, 3, 17, 31, 45, 80, /* - - - 2 w s x down */
208 /*50*/ 1, 15, 41, 2, 16, 30, 44, IGN, /* esc tab ~ 1 q a z - */
209 /*58*/ 221, 42, 29, 29, 56, 56, 54, IGN, /* menu Ls Lc Rc La Ra Rs - */
210 };
211
212 /* Sharp Tripad PV6000 and VADEM CLIO */
213 static char tripad_keytrans[] = {
214 /*00*/ 42, 15, 41, 16, 1, 2, 104, 221, /* lsh tab ` q esc 1 WIN - */
215 /*08*/ 29, 44, 45, 30, 31, 17, 18, 3, /* ctrl z x a s w e 2 */
216 /*10*/ 56, 57, 46, 47, 32, 33, 19, 4, /* lalt sp c v d f r 3 */
217 /*18*/ 48, 49, 34, 35, 20, 21, 5, 6, /* b n g h t y 4 5 */
218 /*20*/ 50, 51, 36, 37, 22, 23, 7, 8, /* m , j k u i 6 7 */
219 /*28*/ 105, 58, 38, 24, 25, 9, 10, 11, /* Fn caps l o p 8 9 0 */
220 /*30*/ 26, 27, 75, 52, 53, 39, 12, 13, /* [ ] la . / ; - = */
221 /*38*/ 54, 77, 72, 80, 40, 28, 43, 14, /* rsh ra ua da ' ent \ del */
222 /*40*/ IGN, IGN, IGN, IGN, IGN, IGN, IGN, IGN, /* - - - - - - - - */
223 /*48*/ IGN, IGN, IGN, IGN, IGN, IGN, IGN, IGN, /* - - - - - - - - */
224 /*50*/ IGN, IGN, IGN, IGN, IGN, IGN, IGN, IGN, /* - - - - - - - - */
225 /*58*/ IGN, IGN, IGN, IGN, IGN, IGN, IGN, IGN, /* - - - - - - - - */
226 };
227
228 /* NEC Mobile Gear MCCS series */
229 static char mccs_keytrans[] = {
230 /*00*/ 58, 28, 77, 25, 52, 21, 48, 44, /* caps cr rar p . y b z */
231 /*08*/ 56, 27, 80, 24, 51, 20, 47, 30, /* alt [ dar o , t v a */
232 /*10*/ 41, 26, 75, 23, 50, 19, 46, 17, /* zen @ lar i m r c w */
233 /*18*/ 29, 39, 72, 22, 49, 18, 45, 16, /* lctrl ; uar u n e x q */
234 /*20*/ 42, 14, 115, 11, 38, 7, 34, 15, /* lshft bs \ 0 l 6 g tab */
235 /*28*/ 123, 125, 53, 10, 37, 6, 33, 3, /* nconv | / 9 k 5 f 2 */
236 /*30*/ 121, 13, 43, 9, 36, 5, 32, 2, /* conv = ] 8 j 4 d 1 */
237 /*38*/ 112, 12, 40, 8, 35, 4, 31, 1, /* hira - ' 7 h 3 s esc */
238 /*40*/ IGN, 57, IGN, IGN, IGN, IGN, IGN, IGN, /* - sp - - - - - - */
239 /*48*/ IGN, IGN, IGN, IGN, IGN, IGN, IGN, IGN, /* - - - - - - - - */
240 /*50*/ IGN, IGN, IGN, IGN, IGN, IGN, IGN, IGN, /* - - - - - - - - */
241 /*58*/ IGN, IGN, IGN, IGN, IGN, IGN, IGN, IGN, /* - - - - - - - - */
242 };
243
244 static char mobilepro_keytrans[] = {
245 /*00*/ 57, 27, 43, 53, 75, 80, 28, 38, /* space ] \ / - - enter l */
246 /*08*/ IGN, 26, 40, 39, 77, 72, 52, 24, /* - [ ' ; - - . o */
247 /*10*/ IGN, IGN, IGN, 221, 47, 46, 45, 44, /* - - - Windows v c x z */
248 /*18*/ IGN, 13, 12, 41, 33, 32, 31, 30, /* - = \- ` f d s a */
249 /*20*/ 9, 8, 7, 6, 19, 18, 17, 16, /* 8 7 6 5 r e w q */
250 /*28*/ 51, 50, 49, 48, IGN, IGN, 11, 10, /* , m n b - - 0 9 */
251 /*30*/ 37, 36, 35, 34, 5, 4, 3, 2, /* k j h g 4 3 2 1 */
252 /*38*/ 23, 22, 21, 20, IGN, 58, 14, 1, /* i u y t - caps del esc */
253 /*40*/ 184, IGN, IGN, IGN, 14, 25, 15, IGN, /* alt_R - - - BS p TAB Fn */
254 /*48*/ IGN, 56, IGN, IGN, 88, 87, 68, 67, /* - alt_L - - f12 f11 f10 f9*/
255 /*50*/ IGN, IGN, 29, IGN, 66, 65, 64, 63, /* - - ctrl - f8 f7 f6 f5 */
256 /*58*/ IGN, IGN, IGN, 42, 62, 61, 60, 59, /* - - - shift f4 f3 f2 f1 */
257 };
258
259 /* NEC MobilePro 750c by "Castor Fu" <castor (at) geocast.com> */
260 static char mobilepro750c_keytrans[] = {
261 /*00*/ 77, 43, 25, 52, 21, 48, 44, 57, /* right \ p . y b z space */
262 /*08*/ 80, 53, 24, 51, 20, 47, 30, IGN, /* down / o , t v a - */
263 /*10*/ 75, 28, 23, 50, 19, 46, 17, 221, /* left enter i m r c w Win */
264 /*18*/ 69, 27, 22, 49, 18, 45, 16, 58, /* num ] u n e x q caps */
265 /*20*/ 81, IGN, 11, 38, 7, 34, 15, 1, /* pgdn - 0 l : g tab esc */
266 /*28*/ IGN, 39, 10, 37, 6, 33, 3, 41, /* - ; 9 k 5 f 2 ` */
267 /*30*/ 72, 26, 9, 36, 5, 32, 2, 40, /* up [ 8 j 4 d 1 ' */
268 /*38*/ 12, 26, 8, 35, 4, 31, 83, IGN, /* - @ 7 h 3 s del - */
269 /*40*/ 42, IGN, IGN, IGN, 14, 88, 66, 62, /* shift - - - bs f12 f8 f4 */
270 /*48*/ IGN, 56, IGN, IGN, 125, 87, 65, 61, /* - alt - - | f11 f7 f3 */
271 /*50*/ IGN, IGN, 29, IGN, 68, 68, 64, 60, /* - - ctrl - f10 f10 f6 f2 */
272 /*58*/ IGN, IGN, IGN, 42, 13, 67, 63, 59, /* - - - shift del f9 f5 f1 */
273 };
274
275 /* FUJITSU INTERTOP CX300 */
276 static char intertop_keytrans[] = {
277 57, 60, 2, 15, 28, 58, 75, 41,
278 112, 59, 3, 16, IGN, 30, 56, 1,
279 210, 17, 4, 31, 83, 43, 80, 45,
280 44, 18, 5, 32, 68, 125, 77, 46,
281 115, 19, 39, 33, 67, 26, 13, 47,
282 53, 20, 6, 34, 66, 25, 12, 48,
283 52, 21, 7, 35, 65, 38, 11, 49,
284 IGN, 22, 8, 36, 63, 24, 14, 50,
285 IGN, 61, 9, 62, IGN, 23, 37, 51,
286 69, 40, 10, 27, 64, IGN, 72, IGN,
287 IGN, IGN, IGN, IGN, 42, IGN, IGN, 54,
288 29, 221, 123, 121, 184, IGN, IGN, IGN,
289 };
290 /*
291 space a2 1 tab enter caps left zenkaku
292 hiraga a1 2 q - a fnc esc
293 ins w 3 s del ] down x
294 z e 4 d a10 \ right c
295 backsla r ; f a9 @ ^ v
296 / t 5 g a8 p - b
297 . y 6 h a7 l 0 n
298 - u 7 j a5 o bs m
299 - a3 8 a4 - i k ,
300 num : 9 [ a6 - up -
301 - - - - shift_L - - shift_R
302 ctrl win muhenka henkan alt - - -
303 */
304
305 static char *keytrans = default_keytrans;
306
307 /*
308 * utilities
309 */
310 static inline void
311 vrkiu_write(chip, port, val)
312 struct vrkiu_chip *chip;
313 int port;
314 unsigned short val;
315 {
316 bus_space_write_2(chip->kc_iot, chip->kc_ioh, port, val);
317 }
318
319 static inline unsigned short
320 vrkiu_read(chip, port)
321 struct vrkiu_chip *chip;
322 int port;
323 {
324 return bus_space_read_2(chip->kc_iot, chip->kc_ioh, port);
325 }
326
327 static inline int
328 vrkiu_is_console(iot, ioh)
329 bus_space_tag_t iot;
330 bus_space_handle_t ioh;
331 {
332 if (vrkiu_consdata &&
333 vrkiu_consdata->kc_iot == iot &&
334 vrkiu_consdata->kc_ioh == ioh) {
335 return 1;
336 } else {
337 return 0;
338 }
339 }
340
341 static void
342 vrkiu_initkeymap(void)
343 {
344 int i;
345 static struct {
346 platid_mask_t *mask;
347 char *keytrans;
348 kbd_t layout;
349 } table[] = {
350 { &platid_mask_MACH_NEC_MCR_500A,
351 mobilepro750c_keytrans, KB_US },
352 { &platid_mask_MACH_NEC_MCR_520A,
353 mobilepro_keytrans, KB_US },
354 { &platid_mask_MACH_NEC_MCR_530A,
355 mobilepro_keytrans, KB_US },
356 { &platid_mask_MACH_NEC_MCR_700A,
357 mobilepro_keytrans, KB_US },
358 { &platid_mask_MACH_NEC_MCR_730A,
359 mobilepro_keytrans, KB_US },
360 { &platid_mask_MACH_NEC_MCR_MPRO700,
361 mobilepro_keytrans, KB_US },
362 { &platid_mask_MACH_NEC_MCR,
363 mcr_jp_keytrans, KB_JP },
364 { &platid_mask_MACH_IBM_WORKPAD_Z50,
365 z50_keytrans, KB_US },
366 { &platid_mask_MACH_SHARP_TRIPAD,
367 tripad_keytrans, KB_US },
368 { &platid_mask_MACH_VADEM_CLIO_C,
369 tripad_keytrans, KB_US },
370 { &platid_mask_MACH_NEC_MCCS,
371 mccs_keytrans, KB_JP },
372 { &platid_mask_MACH_FUJITSU_INTERTOP,
373 intertop_keytrans, KB_JP },
374 { NULL } /* end mark */
375 };
376
377 for (i = 0; table[i].mask; i++) {
378 if (platid_match(&platid, table[i].mask)) {
379 keytrans = table[i].keytrans;
380 #if !defined(PCKBD_LAYOUT)
381 vrkiu_keymapdata.layout = table[i].layout;
382 #endif
383 break;
384 }
385 }
386 }
387
388 /*
389 * initialize device
390 */
391 static int
392 vrkiu_init(chip, iot, ioh)
393 struct vrkiu_chip* chip;
394 bus_space_tag_t iot;
395 bus_space_handle_t ioh;
396 {
397 memset(chip, 0, sizeof(struct vrkiu_chip));
398 chip->kc_iot = iot;
399 chip->kc_ioh = ioh;
400 chip->kc_polling = 0;
401 chip->kc_head = chip->kc_tail = chip->kc_eventq;
402 chip->kc_nevents = 0;
403
404 /* set KIU */
405 vrkiu_write(chip, KIURST, 1); /* reset */
406 vrkiu_write(chip, KIUSCANLINE, 0); /* 96keys */
407 vrkiu_write(chip, KIUWKS, 0x18a4); /* XXX: scan timing! */
408 vrkiu_write(chip, KIUWKI, 450);
409 vrkiu_write(chip, KIUSCANREP, 0x8023);
410 /* KEYEN | STPREP = 2 | ATSTP | ATSCAN */
411 vrkiu_initkeymap();
412 return 0;
413 }
414
415 /*
416 * put key event
417 */
418 static int
419 vrkiu_putevent(chip, type, data)
420 struct vrkiu_chip* chip;
421 u_int type;
422 int data;
423 {
424 if (chip->kc_nevents == NEVENTQ) {
425 return (0);
426 }
427 chip->kc_nevents++;
428 chip->kc_tail->kc_type = type;
429 chip->kc_tail->kc_data = data;
430 if (&chip->kc_eventq[NEVENTQ] <= ++chip->kc_tail) {
431 chip->kc_tail = chip->kc_eventq;
432 }
433 return (1);
434 }
435
436 /*
437 * gut key event
438 */
439 static int
440 vrkiu_getevent(chip, type, data)
441 struct vrkiu_chip* chip;
442 u_int *type;
443 int *data;
444 {
445 if (chip->kc_nevents == 0) {
446 return (0);
447 }
448 *type = chip->kc_head->kc_type;
449 *data = chip->kc_head->kc_data;
450 chip->kc_nevents--;
451 if (&chip->kc_eventq[NEVENTQ] <= ++chip->kc_head) {
452 chip->kc_head = chip->kc_eventq;
453 }
454 return (1);
455 }
456
457 /*
458 * probe
459 */
460 static int
461 vrkiumatch(parent, cf, aux)
462 struct device *parent;
463 struct cfdata *cf;
464 void *aux;
465 {
466 return 1;
467 }
468
469 /*
470 * attach
471 */
472 static void
473 vrkiuattach(parent, self, aux)
474 struct device *parent;
475 struct device *self;
476 void *aux;
477 {
478 struct vrkiu_softc *sc = (struct vrkiu_softc *)self;
479 struct vrip_attach_args *va = aux;
480 struct wskbddev_attach_args wa;
481 int isconsole;
482
483 bus_space_tag_t iot = va->va_iot;
484 bus_space_handle_t ioh;
485
486 if (bus_space_map(iot, va->va_addr, 1, 0, &ioh)) {
487 printf(": can't map bus space\n");
488 return;
489 }
490
491 isconsole = vrkiu_is_console(iot, ioh);
492 if (isconsole) {
493 sc->sc_chip = vrkiu_consdata;
494 } else {
495 sc->sc_chip = &sc->sc_chip_body;
496 vrkiu_init(sc->sc_chip, iot, ioh);
497 }
498 sc->sc_chip->kc_sc = sc;
499
500 if (!(sc->sc_handler =
501 vrip_intr_establish(va->va_vc, va->va_intr, IPL_TTY,
502 vrkiu_intr, sc))) {
503 printf (": can't map interrupt line.\n");
504 return;
505 }
506 /* Level2 register setting */
507 vrip_intr_setmask2(va->va_vc, sc->sc_handler, KIUINT_KDATRDY, 1);
508
509 printf("\n");
510
511 wa.console = isconsole;
512 wa.keymap = &vrkiu_keymapdata;
513 wa.accessops = &vrkiu_accessops;
514 wa.accesscookie = sc;
515
516 sc->sc_wskbddev = config_found(self, &wa, wskbddevprint);
517 }
518
519 int
520 vrkiu_intr(arg)
521 void *arg;
522 {
523 struct vrkiu_softc *sc = arg;
524
525 /* When key scan finisshed, this entry is called. */
526 DPRINTF(("%s(%d): vrkiu_intr: %d\n",
527 __FILE__, __LINE__,
528 vrkiu_read(sc->sc_chip, KIUINT) & 7));
529
530 /*
531 * First, we must clear the interrupt register because
532 * detect_key() may takes long time if a bitmap screen
533 * scrolls up and it makes us to miss some key release
534 * event.
535 */
536 vrkiu_write(sc->sc_chip, KIUINT, 0x7); /* Clear all interrupt */
537 detect_key(sc->sc_chip);
538
539 return 0;
540 }
541
542 static int
543 detect_key(chip)
544 struct vrkiu_chip* chip;
545 {
546 int i, j, modified, mask;
547 int detected;
548 unsigned short scandata[KIU_NSCANLINE/2];
549
550 for (i = 0; i < KIU_NSCANLINE / 2; i++) {
551 scandata[i] = vrkiu_read(chip, KIUDATP + i * 2);
552 }
553
554 DPRINTF(("%s(%d): detect_key():", __FILE__, __LINE__));
555
556 detected = 0;
557 for (i = 0; i < KIU_NSCANLINE / 2; i++) {
558 modified = scandata[i] ^ chip->kc_scandata[i];
559 chip->kc_scandata[i] = scandata[i];
560 mask = 1;
561 for (j = 0; j < 16; j++, mask <<= 1) {
562 /*
563 * Simultaneous keypresses are resolved by registering
564 * the one with the lowest bit index first.
565 */
566 if (modified & mask) {
567 int key, type;
568 key = i * 16 + j;
569 if (keytrans[key] == UNK) {
570 printf("vrkiu: Unknown scan code 0x%02x\n", key);
571 continue;
572 } else if (keytrans[key] == IGN) {
573 continue;
574 }
575 type = (scandata[i] & mask) ?
576 WSCONS_EVENT_KEY_DOWN :
577 WSCONS_EVENT_KEY_UP;
578 DPRINTF(("(%d,%d)=%s%d ", i, j,
579 (scandata[i] & mask) ? "v" : "^",
580 keytrans[key]));
581 detected++;
582 if (chip->kc_polling) {
583 if (vrkiu_putevent(chip, type,
584 keytrans[key]) == 0)
585 printf("vrkiu: queue over flow");
586 } else {
587 #ifdef WSDISPLAY_COMPAT_RAWKBD
588 if (chip->kc_sc->sc_rawkbd) {
589 int n;
590 u_char data[16];
591 n = pckbd_encode(type,
592 keytrans[key], data);
593 wskbd_rawinput(chip->kc_sc->sc_wskbddev, data, n);
594 } else
595 #endif
596 wskbd_input(chip->kc_sc->sc_wskbddev,
597 type,
598 keytrans[key]);
599 }
600 }
601 }
602 }
603 DPRINTF(("\n"));
604
605 return (detected);
606 }
607
608 /* called from biconsdev.c */
609 int
610 vrkiu_getc()
611 {
612 /*
613 * XXX, currently
614 */
615 printf("%s(%d): vrkiu_getc() is not implemented\n",
616 __FILE__, __LINE__);
617 return 0;
618 }
619
620 int
621 vrkiu_enable(scx, on)
622 void *scx;
623 int on;
624 {
625 struct vrkiu_softc *sc = scx;
626
627 if (on) {
628 if (sc->sc_enabled)
629 return (EBUSY);
630 sc->sc_enabled = 1;
631 } else {
632 if (sc->sc_chip == vrkiu_consdata)
633 return (EBUSY);
634 sc->sc_enabled = 0;
635 }
636
637 return (0);
638 }
639
640 void
641 vrkiu_set_leds(scx, leds)
642 void *scx;
643 int leds;
644 {
645 /*struct pckbd_softc *sc = scx;
646 */
647
648 DPRINTF(("%s(%d): vrkiu_set_leds() not implemented\n",
649 __FILE__, __LINE__));
650 }
651
652 int
653 vrkiu_ioctl(scx, cmd, data, flag, p)
654 void *scx;
655 u_long cmd;
656 caddr_t data;
657 int flag;
658 struct proc *p;
659 {
660 #ifdef WSDISPLAY_COMPAT_RAWKBD
661 struct vrkiu_softc *sc = scx;
662 #endif
663
664 switch (cmd) {
665 case WSKBDIO_GTYPE:
666 *(int *)data = WSKBD_TYPE_HPC_KBD;
667 return 0;
668 case WSKBDIO_SETLEDS:
669 DPRINTF(("%s(%d): no LED\n", __FILE__, __LINE__));
670 return 0;
671 case WSKBDIO_GETLEDS:
672 DPRINTF(("%s(%d): no LED\n", __FILE__, __LINE__));
673 *(int *)data = 0;
674 return (0);
675 #ifdef WSDISPLAY_COMPAT_RAWKBD
676 case WSKBDIO_SETMODE:
677 sc->sc_rawkbd = (*(int *)data == WSKBD_RAW);
678 DPRINTF(("%s(%d): rawkbd is %s\n", __FILE__, __LINE__,
679 sc->sc_rawkbd ? "on" : "off"));
680 return (0);
681 #endif
682 }
683 return (-1);
684 }
685
686 /*
687 * console support routines
688 */
689 int
690 vrkiu_cnattach(iot, iobase)
691 bus_space_tag_t iot;
692 int iobase;
693 {
694 static struct vrkiu_chip vrkiu_consdata_body;
695 bus_space_handle_t ioh;
696
697 if (vrkiu_consdata) {
698 panic("vrkiu is already attached as the console");
699 }
700 if (bus_space_map(iot, iobase, 1, 0, &ioh)) {
701 printf("%s(%d): can't map bus space\n", __FILE__, __LINE__);
702 return -1;
703 }
704
705 if (vrkiu_init(&vrkiu_consdata_body, iot, ioh) != 0) {
706 DPRINTF(("%s(%d): vrkiu_init() failed\n", __FILE__, __LINE__));
707 return -1;
708 }
709 vrkiu_consdata = &vrkiu_consdata_body;
710
711 wskbd_cnattach(&vrkiu_consops, vrkiu_consdata, &vrkiu_keymapdata);
712
713 return (0);
714 }
715
716 void
717 vrkiu_cngetc(chipx, type, data)
718 void *chipx;
719 u_int *type;
720 int *data;
721 {
722 struct vrkiu_chip* chip = chipx;
723 int s;
724
725 if (!chip->kc_polling) {
726 printf("%s(%d): kiu is not polled\n", __FILE__, __LINE__);
727 /*
728 * Don't call panic() because it may call this routine
729 * recursively.
730 */
731 printf("halt\n");
732 while (1);
733 }
734
735 s = splimp();
736 while (vrkiu_getevent(chip, type, data) == 0) /* busy loop */
737 detect_key(chip);
738 splx(s);
739 }
740
741 void
742 vrkiu_cnpollc(chipx, on)
743 void *chipx;
744 int on;
745 {
746 struct vrkiu_chip* chip = chipx;
747 int s = splimp();
748
749 chip->kc_polling = on;
750
751 splx(s);
752
753 DPRINTF(("%s(%d): vrkiu polling %s\n",
754 __FILE__, __LINE__, on ? "ON" : "OFF"));
755 }
756