1 /* $NetBSD: vrkiu.c,v 1.37 2005/12/11 12:17:34 christos Exp $ */
4 * Copyright (c) 1999 SASAKI Takesi All rights reserved.
5 * Copyright (c) 1999, 2000, 2002 TAKEMRUA, Shin All rights reserved.
6 * Copyright (c) 1999 PocketBSD Project. All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
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.
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
38 #include <sys/cdefs.h>
39 __KERNEL_RCSID(0, "$NetBSD: vrkiu.c,v 1.37 2005/12/11 12:17:34 christos Exp $");
41 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/device.h>
46 #include <sys/kernel.h>
49 #include <machine/intr.h>
50 #include <machine/cpu.h>
51 #include <machine/bus.h>
52 #include <machine/platid.h>
53 #include <machine/platid_mask.h>
55 #include <dev/hpc/hpckbdvar.h>
57 #include <hpcmips/vr/vr.h>
58 #include <hpcmips/vr/vripif.h>
59 #include <hpcmips/vr/vrkiureg.h>
60 #include <hpcmips/vr/vrkiuvar.h>
61 #include <hpcmips/vr/icureg.h>
63 #include "opt_wsdisplay_compat.h"
64 #include "opt_pckbd_layout.h"
65 #include <dev/wscons/wsconsio.h>
66 #include <dev/wscons/wskbdvar.h>
67 #include <dev/wscons/wsksymdef.h>
68 #include <dev/wscons/wsksymvar.h>
69 #ifdef WSDISPLAY_COMPAT_RAWKBD
70 #include <dev/hpc/pckbd_encode.h>
76 #define DPRINTF(arg) if (vrkiu_debug) printf arg;
81 static int vrkiumatch(struct device
*, struct cfdata
*, void *);
82 static void vrkiuattach(struct device
*, struct device
*, void *);
84 int vrkiu_intr(void *);
86 static int vrkiu_init(struct vrkiu_chip
*, bus_space_tag_t
, bus_space_handle_t
);
87 static void vrkiu_write(struct vrkiu_chip
*, int, unsigned short);
88 static unsigned short vrkiu_read(struct vrkiu_chip
*, int);
89 static int vrkiu_is_console(bus_space_tag_t
, bus_space_handle_t
);
90 static void vrkiu_scan(struct vrkiu_chip
*);
91 static int countbits(int);
92 static void eliminate_phantom_keys(struct vrkiu_chip
*, unsigned short *);
93 static int vrkiu_poll(void*);
94 static int vrkiu_input_establish(void*, struct hpckbd_if
*);
96 CFATTACH_DECL(vrkiu
, sizeof(struct vrkiu_softc
),
97 vrkiumatch
, vrkiuattach
, NULL
, NULL
);
99 struct vrkiu_chip
*vrkiu_consdata
= NULL
;
102 vrkiu_write(struct vrkiu_chip
*chip
, int port
, unsigned short val
)
105 bus_space_write_2(chip
->kc_iot
, chip
->kc_ioh
, port
, val
);
108 static inline unsigned short
109 vrkiu_read(struct vrkiu_chip
*chip
, int port
)
112 return (bus_space_read_2(chip
->kc_iot
, chip
->kc_ioh
, port
));
116 vrkiu_is_console(bus_space_tag_t iot
, bus_space_handle_t ioh
)
119 if (vrkiu_consdata
&&
120 vrkiu_consdata
->kc_iot
== iot
&&
121 vrkiu_consdata
->kc_ioh
== ioh
) {
129 vrkiumatch(struct device
*parent
, struct cfdata
*cf
, void *aux
)
136 vrkiuattach(struct device
*parent
, struct device
*self
, void *aux
)
138 struct vrkiu_softc
*sc
= (struct vrkiu_softc
*)self
;
139 struct vrip_attach_args
*va
= aux
;
140 struct hpckbd_attach_args haa
;
143 bus_space_tag_t iot
= va
->va_iot
;
144 bus_space_handle_t ioh
;
146 if (va
->va_parent_ioh
!= 0)
147 res
= bus_space_subregion(iot
, va
->va_parent_ioh
, va
->va_addr
,
150 res
= bus_space_map(iot
, va
->va_addr
, 1, 0, &ioh
);
152 printf(": can't map bus space\n");
156 isconsole
= vrkiu_is_console(iot
, ioh
);
158 sc
->sc_chip
= vrkiu_consdata
;
160 sc
->sc_chip
= &sc
->sc_chip_body
;
161 vrkiu_init(sc
->sc_chip
, iot
, ioh
);
163 sc
->sc_chip
->kc_sc
= sc
;
165 if (!(sc
->sc_handler
=
166 vrip_intr_establish(va
->va_vc
, va
->va_unit
, 0, IPL_TTY
,
168 printf (": can't map interrupt line.\n");
171 /* Level2 register setting */
172 vrip_intr_setmask2(va
->va_vc
, sc
->sc_handler
, KIUINT_KDATRDY
, 1);
177 haa
.haa_ic
= &sc
->sc_chip
->kc_if
;
178 config_found(self
, &haa
, hpckbd_print
);
185 vrkiu_init(struct vrkiu_chip
*chip
, bus_space_tag_t iot
,
186 bus_space_handle_t ioh
)
189 memset(chip
, 0, sizeof(struct vrkiu_chip
));
192 chip
->kc_enabled
= 0;
194 chip
->kc_if
.hii_ctx
= chip
;
195 chip
->kc_if
.hii_establish
= vrkiu_input_establish
;
196 chip
->kc_if
.hii_poll
= vrkiu_poll
;
199 vrkiu_write(chip
, KIURST
, 1); /* reset */
200 vrkiu_write(chip
, KIUSCANLINE
, 0); /* 96keys */
201 vrkiu_write(chip
, KIUWKS
, 0x18a4); /* XXX: scan timing! */
202 vrkiu_write(chip
, KIUWKI
, 450);
203 vrkiu_write(chip
, KIUSCANREP
, 0x8023);
204 /* KEYEN | STPREP = 2 | ATSTP | ATSCAN */
210 vrkiu_intr(void *arg
)
212 struct vrkiu_softc
*sc
= arg
;
214 /* When key scan finisshed, this entry is called. */
216 DPRINTF(("vrkiu_intr: intr=%x scan=%x\n",
217 vrkiu_read(sc
->sc_chip
, KIUINT
) & 7,
218 vrkiu_read(sc
->sc_chip
, KIUSCANS
) & KIUSCANS_SSTAT_MASK
));
222 * First, we must clear the interrupt register because
223 * vrkiu_scan() may takes long time if a bitmap screen
224 * scrolls up and it makes us to miss some key release
227 vrkiu_write(sc
->sc_chip
, KIUINT
, 0x7); /* Clear all interrupt */
230 /* just return if kiu is scanning keyboard. */
231 if ((vrkiu_read(sc
->sc_chip
, KIUSCANS
) & KIUSCANS_SSTAT_MASK
) ==
232 KIUSCANS_SSTAT_SCANNING
)
235 vrkiu_scan(sc
->sc_chip
);
245 for (i
= 0, n
= 0; i
< NBBY
; i
++)
252 eliminate_phantom_keys(struct vrkiu_chip
*chip
, unsigned short *scandata
)
254 unsigned char inkey
[KIU_NSCANLINE
], *prevkey
, *reskey
;
258 static int prevmod
= 0;
261 reskey
= (unsigned char *)scandata
;
262 for (i
= 0; i
< KIU_NSCANLINE
; i
++)
263 inkey
[i
] = reskey
[i
];
264 prevkey
= (unsigned char *)chip
->kc_scandata
;
266 for (i
= 0; i
< KIU_NSCANLINE
; i
++) {
267 if (countbits(inkey
[i
]) > 1) {
268 for (j
= 0; j
< KIU_NSCANLINE
; j
++) {
269 if (i
!= j
&& (inkey
[i
] & inkey
[j
])) {
273 DPRINTF(("vrkiu_scan: %x:%02x->%02x",
274 i
, inkey
[i
], prevkey
[i
]));
275 DPRINTF((" %x:%02x->%02x\n",
276 j
, inkey
[j
], prevkey
[j
]));
279 reskey
[i
] = prevkey
[i
];
280 reskey
[j
] = prevkey
[j
];
291 vrkiu_scan(struct vrkiu_chip
* chip
)
293 int i
, j
, modified
, mask
;
294 unsigned short scandata
[KIU_NSCANLINE
/2];
296 if (!chip
->kc_enabled
)
299 for (i
= 0; i
< KIU_NSCANLINE
/ 2; i
++) {
300 scandata
[i
] = vrkiu_read(chip
, KIUDATP
+ i
* 2);
302 eliminate_phantom_keys(chip
, scandata
);
304 for (i
= 0; i
< KIU_NSCANLINE
/ 2; i
++) {
305 modified
= scandata
[i
] ^ chip
->kc_scandata
[i
];
306 chip
->kc_scandata
[i
] = scandata
[i
];
308 for (j
= 0; j
< 16; j
++, mask
<<= 1) {
310 * Simultaneous keypresses are resolved by registering
311 * the one with the lowest bit index first.
313 if (modified
& mask
) {
314 int key
= i
* 16 + j
;
315 DPRINTF(("vrkiu_scan: %s(%d,%d)\n",
316 (scandata
[i
] & mask
) ? "down" : "up",
318 hpckbd_input(chip
->kc_hpckbd
,
319 (scandata
[i
] & mask
), key
);
325 /* called from bicons.c */
336 printf("%s(%d): vrkiu_getc() is not implemented\n",
343 * hpckbd interface routines
346 vrkiu_input_establish(void *ic
, struct hpckbd_if
*kbdif
)
348 struct vrkiu_chip
*kc
= ic
;
350 /* save hpckbd interface */
351 kc
->kc_hpckbd
= kbdif
;
361 struct vrkiu_chip
*kc
= ic
;
364 /* wait until kiu completes keyboard scan. */
365 while ((vrkiu_read(kc
, KIUSCANS
) & KIUSCANS_SSTAT_MASK
) ==
366 KIUSCANS_SSTAT_SCANNING
)
367 /* wait until kiu completes keyboard scan */;
376 * console support routine
379 vrkiu_cnattach(bus_space_tag_t iot
, int iobase
)
381 static struct vrkiu_chip vrkiu_consdata_body
;
382 bus_space_handle_t ioh
;
384 if (vrkiu_consdata
) {
385 panic("vrkiu is already attached as the console");
387 if (bus_space_map(iot
, iobase
, 1, 0, &ioh
)) {
388 printf("%s(%d): can't map bus space\n", __FILE__
, __LINE__
);
392 if (vrkiu_init(&vrkiu_consdata_body
, iot
, ioh
) != 0) {
393 DPRINTF(("%s(%d): vrkiu_init() failed\n", __FILE__
, __LINE__
));
396 vrkiu_consdata
= &vrkiu_consdata_body
;
398 hpckbd_cnattach(&vrkiu_consdata_body
.kc_if
);