1 /* $NetBSD: ewskbd.c,v 1.8 2008/03/29 19:15:34 tsutsui Exp $ */
4 * Copyright (c) 2005 Izumi Tsutsui. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 * Copyright (c) 2004 Steve Rumble
29 * All rights reserved.
31 * Redistribution and use in source and binary forms, with or without
32 * modification, are permitted provided that the following conditions
34 * 1. Redistributions of source code must retain the above copyright
35 * notice, this list of conditions and the following disclaimer.
36 * 2. Redistributions in binary form must reproduce the above copyright
37 * notice, this list of conditions and the following disclaimer in the
38 * documentation and/or other materials provided with the distribution.
39 * 3. The name of the author may not be used to endorse or promote products
40 * derived from this software without specific prior written permission.
42 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
43 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
44 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
45 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
46 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
47 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
48 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
49 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
50 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
51 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
55 * EWS4800 serial keyboard driver attached to zs channel 0 at 4800 bps.
56 * This layer is the parent of wskbd.
58 * This driver is taken from sgimips.
61 #include <sys/cdefs.h>
62 __KERNEL_RCSID(0, "$NetBSD: ewskbd.c,v 1.8 2008/03/29 19:15:34 tsutsui Exp $");
64 #include <sys/param.h>
65 #include <sys/malloc.h>
66 #include <sys/systm.h>
68 #include <sys/device.h>
70 #include <dev/wscons/wsconsio.h>
71 #include <dev/wscons/wskbdvar.h>
72 #include <dev/wscons/wsksymdef.h>
73 #include <dev/wscons/wsksymvar.h>
75 #include <dev/ic/z8530reg.h>
76 #include <machine/z8530var.h>
78 #include <ews4800mips/dev/ews4800keymap.h>
80 #define EWSKBD_BAUD 4800
82 #define EWSKBD_TXQ_LEN 16 /* power of 2 */
83 #define EWSKBD_TXQ_LEN_MASK (EWSKBD_TXQ_LEN - 1)
84 #define EWSKBD_NEXTTXQ(x) (((x) + 1) & EWSKBD_TXQ_LEN_MASK)
86 #define EWSKBD_RXQ_LEN 64 /* power of 2 */
87 #define EWSKBD_RXQ_LEN_MASK (EWSKBD_RXQ_LEN - 1)
88 #define EWSKBD_NEXTRXQ(x) (((x) + 1) & EWSKBD_RXQ_LEN_MASK)
90 #define EWSKBD_KEY_UP 0x80
91 #define EWSKBD_KEY_MASK 0x7f
95 #define DPRINTF(_x) if (ewskbd_debug) printf _x
100 struct ewskbd_softc
{
102 struct ewskbd_devconfig
*sc_dc
;
105 struct ewskbd_devconfig
{
106 /* transmit tail-chasing fifo */
107 uint8_t txq
[EWSKBD_TXQ_LEN
];
111 /* receive tail-chasing fifo */
112 uint8_t rxq
[EWSKBD_RXQ_LEN
];
118 #define TX_READY 0x01
122 #define EWSKBD_SETLEDS 0x90
123 #define EWSKBD_CAPSLOCK 0x02
124 #define EWSKBD_KANA 0x04
127 struct device
*wskbddev
;
131 static int ewskbd_zsc_match(device_t
, cfdata_t
, void *);
132 static void ewskbd_zsc_attach(device_t
, device_t
, void *);
133 static int ewskbd_zsc_init(struct zs_chanstate
*);
134 static void ewskbd_zsc_rxint(struct zs_chanstate
*);
135 static void ewskbd_zsc_stint(struct zs_chanstate
*, int);
136 static void ewskbd_zsc_txint(struct zs_chanstate
*);
137 static void ewskbd_zsc_softint(struct zs_chanstate
*);
138 static void ewskbd_zsc_send(struct zs_chanstate
*, uint8_t *, u_int
);
140 static void ewskbd_wskbd_input(struct zs_chanstate
*, u_char
);
141 static int ewskbd_wskbd_enable(void *, int);
142 static void ewskbd_wskbd_set_leds(void *, int);
143 static int ewskbd_wskbd_get_leds(void *);
144 static int ewskbd_wskbd_ioctl(void *, u_long
, void *, int, struct lwp
*);
146 void ewskbd_zsc_cnattach(uint32_t, uint32_t, int);
147 static void ewskbd_zsc_wskbd_getc(void *, u_int
*, int *);
148 static void ewskbd_wskbd_pollc(void *, int);
149 static void ewskbd_wskbd_bell(void *, u_int
, u_int
, u_int
);
151 CFATTACH_DECL_NEW(ewskbd_zsc
, sizeof(struct ewskbd_softc
),
152 ewskbd_zsc_match
, ewskbd_zsc_attach
, NULL
, NULL
);
154 static struct zsops ewskbd_zsops
= {
161 const struct wskbd_mapdata ews4800kbd_wskbd_keymapdata
= {
162 ews4800kbd_keydesctab
,
166 const struct wskbd_accessops ewskbd_wskbd_accessops
= {
168 ewskbd_wskbd_set_leds
,
172 const struct wskbd_consops ewskbd_wskbd_consops
= {
173 ewskbd_zsc_wskbd_getc
,
178 static struct ewskbd_devconfig ewskbd_console_dc
;
179 static struct zs_chanstate conschan
;
180 static int ewskbd_is_console
;
183 ewskbd_zsc_match(device_t parent
, cfdata_t cf
, void *aux
)
185 struct zsc_attach_args
*zsc_args
= aux
;
186 struct zsc_softc
*zsc
= device_private(parent
);
188 /* keyboard is on channel B */
189 if ((zsc
->zsc_flags
& 0x0001 /* kbms port */) != 0 &&
190 zsc_args
->channel
== 1)
191 /* prior to generic zstty(4) */
198 ewskbd_zsc_attach(struct device
*parent
, struct device
*self
, void *aux
)
200 struct ewskbd_softc
*sc
;
201 struct zsc_softc
*zsc
;
202 struct zs_chanstate
*cs
;
203 struct zsc_attach_args
*zsc_args
;
204 struct wskbddev_attach_args wskaa
;
207 sc
= device_private(self
);
208 zsc
= device_private(parent
);
212 /* Establish ourself with the MD z8530 driver */
213 channel
= zsc_args
->channel
;
214 cs
= zsc
->zsc_cs
[channel
];
216 if (ewskbd_is_console
) {
217 sc
->sc_dc
= &ewskbd_console_dc
;
219 sc
->sc_dc
->enabled
= 1;
223 sc
->sc_dc
= malloc(sizeof(struct ewskbd_devconfig
), M_DEVBUF
,
225 if (sc
->sc_dc
== NULL
) {
226 printf(": can't allocate memory\n");
229 sc
->sc_dc
->enabled
= 0;
231 cs
->cs_defspeed
= EWSKBD_BAUD
;
232 cs
->cs_ops
= &ewskbd_zsops
;
235 sc
->sc_dc
->txq_head
= 0;
236 sc
->sc_dc
->txq_tail
= 0;
237 sc
->sc_dc
->rxq_head
= 0;
238 sc
->sc_dc
->rxq_tail
= 0;
239 sc
->sc_dc
->state
= TX_READY
;
244 /* set default LED */
245 ewskbd_wskbd_set_leds(cs
, 0);
247 printf(": baud rate %d\n", EWSKBD_BAUD
);
250 wskaa
.keymap
= &ews4800kbd_wskbd_keymapdata
;
251 wskaa
.accessops
= &ewskbd_wskbd_accessops
;
252 wskaa
.accesscookie
= cs
;
253 sc
->sc_dc
->wskbddev
= config_found(self
, &wskaa
, wskbddevprint
);
257 ewskbd_zsc_init(struct zs_chanstate
*cs
)
263 zs_write_reg(cs
, 9, ZSWR9_B_RESET
);
265 zs_write_reg(cs
, 9, ZSWR9_MASTER_IE
| ZSWR9_NO_VECTOR
);
267 cs
->cs_preg
[1] = ZSWR1_RIE
| ZSWR1_TIE
;
269 cs
->cs_preg
[3] = ZSWR3_RX_8
| ZSWR3_RX_ENABLE
;
270 cs
->cs_preg
[4] = ZSWR4_CLK_X16
| ZSWR4_ONESB
| ZSWR4_PARENB
;
271 cs
->cs_preg
[5] = ZSWR5_TX_8
| ZSWR5_RTS
| ZSWR5_TX_ENABLE
;
275 cs
->cs_preg
[9] = ZSWR9_MASTER_IE
| ZSWR9_NO_VECTOR
;
277 cs
->cs_preg
[11] = ZSWR11_RXCLK_BAUD
| ZSWR11_TXCLK_BAUD
|
278 ZSWR11_TRXC_OUT_ENA
| ZSWR11_TRXC_BAUD
;
279 /* reg[11] and reg[12] are set by zs_set_speed() with cs_brg_clk */
280 zs_set_speed(cs
, EWSKBD_BAUD
);
281 cs
->cs_preg
[14] = ZSWR14_BAUD_FROM_PCLK
| ZSWR14_BAUD_ENA
;
284 zs_loadchannelregs(cs
);
292 ewskbd_zsc_rxint(struct zs_chanstate
*cs
)
294 struct ewskbd_softc
*sc
;
295 struct ewskbd_devconfig
*dc
;
302 r
= zs_read_reg(cs
, 1);
303 if (r
& (ZSRR1_FE
| ZSRR1_DO
| ZSRR1_PE
))
304 zs_write_csr(cs
, ZSWR0_RESET_ERRORS
);
306 /* read byte and append to our queue */
307 c
= zs_read_data(cs
);
309 dc
->rxq
[dc
->rxq_tail
] = c
;
310 dc
->rxq_tail
= EWSKBD_NEXTRXQ(dc
->rxq_tail
);
316 ewskbd_zsc_stint(struct zs_chanstate
*cs
, int force
)
319 zs_write_csr(cs
, ZSWR0_RESET_STATUS
);
324 ewskbd_zsc_txint(struct zs_chanstate
*cs
)
326 struct ewskbd_softc
*sc
;
329 zs_write_reg(cs
, 0, ZSWR0_RESET_TXINT
);
330 sc
->sc_dc
->state
|= TX_READY
;
335 ewskbd_zsc_softint(struct zs_chanstate
*cs
)
337 struct ewskbd_softc
*sc
;
338 struct ewskbd_devconfig
*dc
;
343 /* handle pending transmissions */
344 if (dc
->txq_head
!= dc
->txq_tail
&& (dc
->state
& TX_READY
)) {
347 dc
->state
&= ~TX_READY
;
350 zs_write_data(cs
, dc
->txq
[dc
->txq_head
]);
353 dc
->txq_head
= EWSKBD_NEXTTXQ(dc
->txq_head
);
356 /* don't bother if nobody is listening */
358 dc
->rxq_head
= dc
->rxq_tail
;
362 /* handle incoming keystrokes/config */
363 while (dc
->rxq_head
!= dc
->rxq_tail
) {
364 uint8_t key
= dc
->rxq
[dc
->rxq_head
];
366 /* toss wskbd a bone */
367 ewskbd_wskbd_input(cs
, key
);
369 dc
->rxq_head
= EWSKBD_NEXTRXQ(dc
->rxq_head
);
373 /* expects to be in splzs() */
375 ewskbd_zsc_send(struct zs_chanstate
*cs
, uint8_t *c
, u_int len
)
377 struct ewskbd_softc
*sc
;
378 struct ewskbd_devconfig
*dc
;
384 for (i
= 0; i
< len
; i
++) {
385 if (dc
->state
& TX_READY
) {
386 zs_write_data(cs
, c
[i
]);
387 dc
->state
&= ~TX_READY
;
389 dc
->txq
[dc
->txq_tail
] = c
[i
];
390 dc
->txq_tail
= EWSKBD_NEXTTXQ(dc
->txq_tail
);
396 /******************************************************************************
398 ******************************************************************************/
401 ewskbd_wskbd_input(struct zs_chanstate
*cs
, uint8_t key
)
403 struct ewskbd_softc
*sc
;
408 if (key
& EWSKBD_KEY_UP
)
409 type
= WSCONS_EVENT_KEY_UP
;
411 type
= WSCONS_EVENT_KEY_DOWN
;
413 wskbd_input(sc
->sc_dc
->wskbddev
, type
, (key
& EWSKBD_KEY_MASK
));
415 DPRINTF(("ewskbd_wskbd_input: inputted key 0x%x\n", key
));
417 #ifdef WSDISPLAY_COMPAT_RAWKBD
418 wskbd_rawinput(sc
->sc_dc
->wskbddev
, &key
, 1);
423 ewskbd_wskbd_enable(void *cookie
, int on
)
425 struct zs_chanstate
*cs
;
426 struct ewskbd_softc
*sc
;
432 if (sc
->sc_dc
->enabled
)
435 sc
->sc_dc
->enabled
= 1;
437 sc
->sc_dc
->enabled
= 0;
439 DPRINTF(("ewskbd_wskbd_enable: %s\n", on
? "enabled" : "disabled"));
445 ewskbd_wskbd_set_leds(void *cookie
, int leds
)
447 struct zs_chanstate
*cs
;
448 struct ewskbd_softc
*sc
;
456 if (leds
& WSKBD_LED_CAPS
)
457 cmd
|= EWSKBD_CAPSLOCK
;
459 sc
->sc_dc
->leds
= cmd
;
461 cmd
|= EWSKBD_SETLEDS
;
464 ewskbd_zsc_send(cs
, &cmd
, 1);
469 ewskbd_wskbd_get_leds(void *cookie
)
471 struct zs_chanstate
*cs
;
472 struct ewskbd_softc
*sc
;
479 if (sc
->sc_dc
->leds
& EWSKBD_CAPSLOCK
)
480 leds
|= WSKBD_LED_CAPS
;
486 ewskbd_wskbd_ioctl(void *cookie
, u_long cmd
, void *data
, int flag
,
492 *(int *)data
= WSKBD_TYPE_EWS4800
;
497 case WSKBDIO_COMPLEXBELL
:
498 case WSKBDIO_SETBELL
:
499 case WSKBDIO_GETBELL
:
500 case WSKBDIO_SETDEFAULTBELL
:
501 case WSKBDIO_GETDEFAULTBELL
:
502 case WSKBDIO_SETKEYREPEAT
:
503 case WSKBDIO_GETKEYREPEAT
:
504 case WSKBDIO_SETDEFAULTKEYREPEAT
:
505 case WSKBDIO_GETDEFAULTKEYREPEAT
:
508 case WSKBDIO_SETLEDS
:
509 ewskbd_wskbd_set_leds(cookie
, *(int *)data
);
512 case WSKBDIO_GETLEDS
:
513 *(int *)data
= ewskbd_wskbd_get_leds(cookie
);
519 case WSKBDIO_GETENCODING
:
520 case WSKBDIO_SETENCODING
:
521 case WSKBDIO_SETMODE
:
522 case WSKBDIO_GETMODE
:
523 case WSKBDIO_SETKEYCLICK
:
524 case WSKBDIO_GETKEYCLICK
:
538 ewskbd_zsc_cnattach(uint32_t csr
, uint32_t data
, int pclk
)
540 struct zs_chanstate
*cs
;
544 cs
->cs_reg_csr
= (void *)csr
;
545 cs
->cs_reg_data
= (void *)data
;
546 cs
->cs_brg_clk
= pclk
/ 16;
547 cs
->cs_defspeed
= EWSKBD_BAUD
;
551 zs_putc(cs
, EWSKBD_SETLEDS
);
553 wskbd_cnattach(&ewskbd_wskbd_consops
, cs
, &ews4800kbd_wskbd_keymapdata
);
554 ewskbd_is_console
= 1;
558 ewskbd_zsc_wskbd_getc(void *cookie
, u_int
*type
, int *data
)
562 key
= zs_getc(cookie
);
564 if (key
& EWSKBD_KEY_UP
)
565 *type
= WSCONS_EVENT_KEY_UP
;
567 *type
= WSCONS_EVENT_KEY_DOWN
;
569 *data
= key
& EWSKBD_KEY_MASK
;
573 ewskbd_wskbd_pollc(void *cookie
, int on
)
576 static bool __polling
= false;
579 if (on
&& !__polling
) {
580 /* disable interrupt driven I/O */
583 } else if (!on
&& __polling
) {
584 /* enable interrupt driven I/O */
591 ewskbd_wskbd_bell(void *cookie
, u_int pitch
, u_int period
, u_int volume
)