vrkiu.c revision 1.23 1 /* $NetBSD: vrkiu.c,v 1.23 2000/07/22 08:26:00 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 bicons.c */
609 int
610 vrkiu_getc()
611 {
612 static int flag = 1;
613
614 /*
615 * XXX, currently
616 */
617 if (flag) {
618 flag = 0;
619 printf("%s(%d): vrkiu_getc() is not implemented\n",
620 __FILE__, __LINE__);
621 }
622 return 0;
623 }
624
625 int
626 vrkiu_enable(scx, on)
627 void *scx;
628 int on;
629 {
630 struct vrkiu_softc *sc = scx;
631
632 if (on) {
633 if (sc->sc_enabled)
634 return (EBUSY);
635 sc->sc_enabled = 1;
636 } else {
637 if (sc->sc_chip == vrkiu_consdata)
638 return (EBUSY);
639 sc->sc_enabled = 0;
640 }
641
642 return (0);
643 }
644
645 void
646 vrkiu_set_leds(scx, leds)
647 void *scx;
648 int leds;
649 {
650 /*struct pckbd_softc *sc = scx;
651 */
652
653 DPRINTF(("%s(%d): vrkiu_set_leds() not implemented\n",
654 __FILE__, __LINE__));
655 }
656
657 int
658 vrkiu_ioctl(scx, cmd, data, flag, p)
659 void *scx;
660 u_long cmd;
661 caddr_t data;
662 int flag;
663 struct proc *p;
664 {
665 #ifdef WSDISPLAY_COMPAT_RAWKBD
666 struct vrkiu_softc *sc = scx;
667 #endif
668
669 switch (cmd) {
670 case WSKBDIO_GTYPE:
671 *(int *)data = WSKBD_TYPE_HPC_KBD;
672 return 0;
673 case WSKBDIO_SETLEDS:
674 DPRINTF(("%s(%d): no LED\n", __FILE__, __LINE__));
675 return 0;
676 case WSKBDIO_GETLEDS:
677 DPRINTF(("%s(%d): no LED\n", __FILE__, __LINE__));
678 *(int *)data = 0;
679 return (0);
680 #ifdef WSDISPLAY_COMPAT_RAWKBD
681 case WSKBDIO_SETMODE:
682 sc->sc_rawkbd = (*(int *)data == WSKBD_RAW);
683 DPRINTF(("%s(%d): rawkbd is %s\n", __FILE__, __LINE__,
684 sc->sc_rawkbd ? "on" : "off"));
685 return (0);
686 #endif
687 }
688 return (-1);
689 }
690
691 /*
692 * console support routines
693 */
694 int
695 vrkiu_cnattach(iot, iobase)
696 bus_space_tag_t iot;
697 int iobase;
698 {
699 static struct vrkiu_chip vrkiu_consdata_body;
700 bus_space_handle_t ioh;
701
702 if (vrkiu_consdata) {
703 panic("vrkiu is already attached as the console");
704 }
705 if (bus_space_map(iot, iobase, 1, 0, &ioh)) {
706 printf("%s(%d): can't map bus space\n", __FILE__, __LINE__);
707 return -1;
708 }
709
710 if (vrkiu_init(&vrkiu_consdata_body, iot, ioh) != 0) {
711 DPRINTF(("%s(%d): vrkiu_init() failed\n", __FILE__, __LINE__));
712 return -1;
713 }
714 vrkiu_consdata = &vrkiu_consdata_body;
715
716 wskbd_cnattach(&vrkiu_consops, vrkiu_consdata, &vrkiu_keymapdata);
717
718 return (0);
719 }
720
721 void
722 vrkiu_cngetc(chipx, type, data)
723 void *chipx;
724 u_int *type;
725 int *data;
726 {
727 struct vrkiu_chip* chip = chipx;
728 int s;
729
730 if (!chip->kc_polling) {
731 printf("%s(%d): kiu is not polled\n", __FILE__, __LINE__);
732 /*
733 * Don't call panic() because it may call this routine
734 * recursively.
735 */
736 printf("halt\n");
737 while (1);
738 }
739
740 s = splimp();
741 while (vrkiu_getevent(chip, type, data) == 0) /* busy loop */
742 detect_key(chip);
743 splx(s);
744 }
745
746 void
747 vrkiu_cnpollc(chipx, on)
748 void *chipx;
749 int on;
750 {
751 struct vrkiu_chip* chip = chipx;
752 int s = splimp();
753
754 chip->kc_polling = on;
755
756 splx(s);
757
758 DPRINTF(("%s(%d): vrkiu polling %s\n",
759 __FILE__, __LINE__, on ? "ON" : "OFF"));
760 }
761