1 /* $NetBSD: kbd.c,v 1.39 2009/07/03 14:00:41 tsutsui Exp $ */
4 * Copyright (c) 1995 Leo Weppelman
5 * Copyright (c) 1982, 1986, 1990 The Regents of the University of California.
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. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 #include <sys/cdefs.h>
34 __KERNEL_RCSID(0, "$NetBSD: kbd.c,v 1.39 2009/07/03 14:00:41 tsutsui Exp $");
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/device.h>
43 #include <sys/ioctl.h>
48 #include <sys/kernel.h>
49 #include <sys/signalvar.h>
50 #include <sys/syslog.h>
52 #include <machine/cpu.h>
53 #include <machine/iomap.h>
54 #include <machine/mfp.h>
55 #include <machine/acia.h>
56 #include <atari/dev/itevar.h>
57 #include <atari/dev/event_var.h>
58 #include <atari/dev/vuid_event.h>
59 #include <atari/dev/ym2149reg.h>
60 #include <atari/dev/kbdreg.h>
61 #include <atari/dev/kbdvar.h>
62 #include <atari/dev/kbdmap.h>
63 #include <atari/dev/msvar.h>
66 #include <dev/wscons/wsconsio.h>
67 #include <dev/wscons/wskbdvar.h>
68 #include <dev/wscons/wsksymdef.h>
69 #include <dev/wscons/wsksymvar.h>
70 #include <atari/dev/wskbdmap_atari.h>
75 * If NWSKBD>0 we try to attach an wskbd device to us. What follows
76 * is definitions of callback functions and structures that are passed
77 * to wscons when initializing.
81 * Now with wscons this driver exhibits some weird behaviour.
82 * It may act both as a driver of its own and the md part of the
83 * wskbd driver. Therefore it can be accessed through /dev/kbd
84 * and /dev/wskbd0 both.
86 * The data from they keyboard may end up in at least four different
88 * - If this driver has been opened (/dev/kbd) and the
89 * direct mode (TIOCDIRECT) has been set, data goes to
90 * the process who opened the device. Data will transmit itself
91 * as described by the firm_event structure.
92 * - If wskbd support is compiled in and a wskbd driver has been
93 * attached then the data is sent to it. Wskbd in turn may
94 * - Send the data in the wscons_event form to a process that
95 * has opened /dev/wskbd0
96 * - Feed the data to a virtual terminal.
97 * - If an ite is present the data may be fed to it.
100 uint8_t kbd_modifier
; /* Modifier mask */
102 static uint8_t kbd_ring
[KBD_RING_SIZE
];
103 static volatile u_int kbd_rbput
= 0; /* 'put' index */
104 static u_int kbd_rbget
= 0; /* 'get' index */
106 static struct kbd_softc kbd_softc
;
108 /* {b,c}devsw[] function prototypes */
109 dev_type_open(kbdopen
);
110 dev_type_close(kbdclose
);
111 dev_type_read(kbdread
);
112 dev_type_ioctl(kbdioctl
);
113 dev_type_poll(kbdpoll
);
114 dev_type_kqfilter(kbdkqfilter
);
116 /* Interrupt handler */
119 static void kbdsoft(void *);
120 static void kbdattach(struct device
*, struct device
*, void *);
121 static int kbdmatch(struct device
*, struct cfdata
*, void *);
123 static int kbd_do_modifier(uint8_t);
125 static int kbd_write_poll(const uint8_t *, int);
126 static void kbd_pkg_start(struct kbd_softc
*, uint8_t);
128 CFATTACH_DECL(kbd
, sizeof(struct device
),
129 kbdmatch
, kbdattach
, NULL
, NULL
);
131 const struct cdevsw kbd_cdevsw
= {
132 kbdopen
, kbdclose
, kbdread
, nowrite
, kbdioctl
,
133 nostop
, notty
, kbdpoll
, nommap
, kbdkqfilter
,
138 static int kbd_enable(void *, int);
139 static void kbd_set_leds(void *, int);
140 static int kbd_ioctl(void *, u_long
, void *, int, struct lwp
*);
143 static void kbd_getc(void *, u_int
*, int *);
144 static void kbd_pollc(void *, int);
145 static void kbd_bell(void *, u_int
, u_int
, u_int
);
147 static struct wskbd_accessops kbd_accessops
= {
153 static struct wskbd_consops kbd_consops
= {
159 /* Pointer to keymaps. */
160 static struct wskbd_mapdata kbd_mapdata
= {
168 kbdmatch(struct device
*pdp
, struct cfdata
*cfp
, void *auxp
)
171 if (!strcmp((char *)auxp
, "kbd"))
178 kbdattach(struct device
*pdp
, struct device
*dp
, void *auxp
)
181 const uint8_t kbd_rst
[] = { 0x80, 0x01 };
182 const uint8_t kbd_icmd
[] = { 0x12, 0x15 };
185 * Disable keyboard interrupts from MFP
187 MFP
->mf_ierb
&= ~IB_AINT
;
190 * Reset ACIA and intialize to:
191 * divide by 16, 8 data, 1 stop, no parity, enable RX interrupts
193 KBD
->ac_cs
= A_RESET
;
194 delay(100); /* XXX: enough? */
195 KBD
->ac_cs
= kbd_softc
.k_soft_cs
= KBD_INIT
| A_RXINT
;
198 * Clear error conditions
200 while (KBD
->ac_cs
& (A_IRQ
|A_RXRDY
))
201 timeout
= KBD
->ac_da
;
204 * Now send the reset string, and read+ignore it's response
206 if (!kbd_write_poll(kbd_rst
, 2))
207 printf("kbd: error cannot reset keyboard\n");
208 for (timeout
= 1000; timeout
> 0; timeout
--) {
209 if (KBD
->ac_cs
& (A_IRQ
|A_RXRDY
)) {
210 timeout
= KBD
->ac_da
;
216 * Send init command: disable mice & joysticks
218 kbd_write_poll(kbd_icmd
, sizeof(kbd_icmd
));
222 kbd_softc
.k_sicookie
= softint_establish(SOFTINT_SERIAL
, kbdsoft
, NULL
);
227 * Try to attach the wskbd.
229 struct wskbddev_attach_args waa
;
231 /* Maybe should be done before this?... */
232 wskbd_cnattach(&kbd_consops
, NULL
, &kbd_mapdata
);
235 waa
.keymap
= &kbd_mapdata
;
236 waa
.accessops
= &kbd_accessops
;
237 waa
.accesscookie
= NULL
;
238 kbd_softc
.k_wskbddev
= config_found(dp
, &waa
, wskbddevprint
);
240 kbd_softc
.k_pollingmode
= 0;
255 * Clear error conditions...
257 while (KBD
->ac_cs
& (A_IRQ
|A_RXRDY
))
260 * Enable interrupts from MFP
262 MFP
->mf_iprb
= (u_int8_t
)~IB_AINT
;
263 MFP
->mf_ierb
|= IB_AINT
;
264 MFP
->mf_imrb
|= IB_AINT
;
266 kbd_softc
.k_event_mode
= 0;
267 kbd_softc
.k_events
.ev_io
= 0;
268 kbd_softc
.k_pkg_size
= 0;
272 int kbdopen(dev_t dev
, int flags
, int mode
, struct lwp
*l
)
275 if (kbd_softc
.k_events
.ev_io
)
278 kbd_softc
.k_events
.ev_io
= l
->l_proc
;
279 ev_init(&kbd_softc
.k_events
);
284 kbdclose(dev_t dev
, int flags
, int mode
, struct lwp
*l
)
287 /* Turn off event mode, dump the queue */
288 kbd_softc
.k_event_mode
= 0;
289 ev_fini(&kbd_softc
.k_events
);
290 kbd_softc
.k_events
.ev_io
= NULL
;
295 kbdread(dev_t dev
, struct uio
*uio
, int flags
)
298 return ev_read(&kbd_softc
.k_events
, uio
, flags
);
302 kbdioctl(dev_t dev
, u_long cmd
, register void *data
, int flag
, struct lwp
*l
)
304 register struct kbd_softc
*k
= &kbd_softc
;
309 if (*(int *)data
== TR_UNTRANS_EVENT
)
315 * Get translation mode
317 *(int *)data
= TR_UNTRANS_EVENT
;
321 k
->k_event_mode
= *(int *)data
;
325 kb
= (struct kbdbell
*)data
;
327 kbd_bell_sparms(kb
->volume
, kb
->pitch
,
332 case FIONBIO
: /* we will remove this someday (soon???) */
336 k
->k_events
.ev_async
= *(int *)data
!= 0;
340 if (-*(int *)data
!= k
->k_events
.ev_io
->p_pgid
341 && *(int *)data
!= k
->k_events
.ev_io
->p_pid
)
346 if (*(int *)data
!= k
->k_events
.ev_io
->p_pgid
)
355 * We identified the ioctl, but we do not handle it.
357 return EOPNOTSUPP
; /* misuse, but what the heck */
361 kbdpoll (dev_t dev
, int events
, struct lwp
*l
)
364 return ev_poll(&kbd_softc
.k_events
, events
, l
);
368 kbdkqfilter(dev_t dev
, struct knote
*kn
)
371 return ev_kqfilter(&kbd_softc
.k_events
, kn
);
375 * Keyboard interrupt handler called straight from MFP at spl6.
379 /* sr: sr at time of interrupt */
385 * There may be multiple keys available. Read them all.
387 while (KBD
->ac_cs
& (A_RXRDY
|A_OE
|A_PE
)) {
389 if (KBD
->ac_cs
& (A_OE
|A_PE
)) {
390 code
= KBD
->ac_da
; /* Silently ignore errors */
393 kbd_ring
[kbd_rbput
++ & KBD_RING_MASK
] = KBD
->ac_da
;
397 * If characters are waiting for transmit, send them.
399 if ((kbd_softc
.k_soft_cs
& A_TXINT
) && (KBD
->ac_cs
& A_TXRDY
)) {
400 if (kbd_softc
.k_sendp
!= NULL
)
401 KBD
->ac_da
= *kbd_softc
.k_sendp
++;
402 if (--kbd_softc
.k_send_cnt
<= 0) {
404 * The total package has been transmitted,
405 * wakeup anyone waiting for it.
407 KBD
->ac_cs
= (kbd_softc
.k_soft_cs
&= ~A_TXINT
);
408 kbd_softc
.k_sendp
= NULL
;
409 kbd_softc
.k_send_cnt
= 0;
410 wakeup((void *)&kbd_softc
.k_send_cnt
);
415 * Activate software-level to handle possible input.
418 softint_schedule(kbd_softc
.k_sicookie
);
422 * Keyboard soft interrupt handler
429 struct kbd_softc
*k
= &kbd_softc
;
430 struct firm_event
*fe
;
437 if (get
== n
) /* We're done */
440 if (n
> KBD_RING_SIZE
) { /* Ring buffer overflow */
441 get
+= n
- KBD_RING_SIZE
;
445 code
= kbd_ring
[get
++ & KBD_RING_MASK
];
448 * If collecting a package, stuff it in and
451 if (k
->k_pkg_size
&& (k
->k_pkg_idx
< k
->k_pkg_size
)) {
452 k
->k_package
[k
->k_pkg_idx
++] = code
;
453 if (k
->k_pkg_idx
== k
->k_pkg_size
) {
455 * Package is complete.
457 switch (k
->k_pkg_type
) {
462 mouse_soft((REL_MOUSE
*)k
->k_package
,
463 k
->k_pkg_size
, k
->k_pkg_type
);
471 * If this is a package header, init pkg. handling.
473 if (!KBD_IS_KEY(code
)) {
474 kbd_pkg_start(k
, code
);
479 * If we have attached a wskbd and not in polling mode
480 * and nobody has opened us directly, then send the
481 * keystroke to the wskbd.
484 if (kbd_softc
.k_pollingmode
== 0
485 && kbd_softc
.k_wskbddev
!= NULL
486 && k
->k_event_mode
== 0) {
487 wskbd_input(kbd_softc
.k_wskbddev
,
489 WSCONS_EVENT_KEY_UP
:
490 WSCONS_EVENT_KEY_DOWN
,
496 if (kbd_do_modifier(code
) && !k
->k_event_mode
)
501 * if not in event mode, deliver straight to ite to
504 if (!k
->k_event_mode
) {
505 /* Gets to spltty() by itself */
507 ite_filter(code
, ITEFILT_TTY
);
513 * Keyboard is generating events. Turn this keystroke
514 * into an event and put it in the queue. If the queue
515 * is full, the keystroke is lost (sorry!).
518 put
= k
->k_events
.ev_put
;
519 fe
= &k
->k_events
.ev_q
[put
];
520 put
= (put
+ 1) % EV_QSIZE
;
521 if (put
== k
->k_events
.ev_get
) {
523 "keyboard event queue overflow\n");
527 fe
->id
= KBD_SCANCODE(code
);
528 fe
->value
= KBD_RELEASED(code
) ? VKEY_UP
: VKEY_DOWN
;
530 k
->k_events
.ev_put
= put
;
531 EV_WAKEUP(&k
->k_events
);
538 static uint8_t sound
[] = {
539 0xA8, 0x01, 0xA9, 0x01, 0xAA, 0x01, 0x00,
540 0xF8, 0x10, 0x10, 0x10, 0x00, 0x20, 0x03
549 for (i
= 0; i
< sizeof(sound
); i
++) {
551 YM2149
->sd_wdat
= sound
[i
];
558 * Set the parameters of the 'default' beep.
561 #define KBDBELLCLOCK 125000 /* 2MHz / 16 */
562 #define KBDBELLDURATION 128 /* 256 / 2MHz */
565 kbd_bell_gparms(u_int
*volume
, u_int
*pitch
, u_int
*duration
)
569 tmp
= sound
[11] | (sound
[12] << 8);
570 *duration
= (tmp
* KBDBELLDURATION
) / 1000;
572 tmp
= sound
[0] | (sound
[1] << 8);
573 *pitch
= KBDBELLCLOCK
/ tmp
;
579 kbd_bell_sparms(u_int volume
, u_int pitch
, u_int duration
)
583 f
= pitch
> 10 ? pitch
: 10; /* minimum pitch */
585 f
= 20000; /* maximum pitch */
587 f
= KBDBELLCLOCK
/ f
;
589 t
= (duration
* 1000) / KBDBELLDURATION
;
591 sound
[ 0] = f
& 0xff;
592 sound
[ 1] = (f
>> 8) & 0xf;
594 sound
[ 2] = f
& 0xff;
595 sound
[ 3] = (f
>> 8) & 0xf;
597 sound
[ 4] = f
& 0xff;
598 sound
[ 5] = (f
>> 8) & 0xf;
600 sound
[11] = t
& 0xff;
601 sound
[12] = (t
>> 8) & 0xff;
614 if (MFP
->mf_imrb
& IB_AINT
) {
616 MFP
->mf_imrb
&= ~IB_AINT
;
619 while (!((KBD
->ac_cs
& (A_IRQ
|A_RXRDY
)) == (A_IRQ
|A_RXRDY
)))
621 if (KBD
->ac_cs
& (A_OE
|A_PE
)) {
622 code
= KBD
->ac_da
; /* Silently ignore errors */
627 if (!kbd_do_modifier(code
))
633 MFP
->mf_iprb
= (uint8_t)~IB_AINT
;
634 MFP
->mf_imrb
|= IB_AINT
;
642 * Write a command to the keyboard in 'polled' mode.
645 kbd_write_poll(const uint8_t *cmd
, int len
)
651 for (timeout
= 100; !(KBD
->ac_cs
& A_TXRDY
); timeout
--)
653 if ((KBD
->ac_cs
& A_TXRDY
) == 0)
660 * Write a command to the keyboard. Return when command is send.
663 kbd_write(const uint8_t *cmd
, int len
)
665 struct kbd_softc
*k
= &kbd_softc
;
669 * Get to splhigh, 'real' interrupts arrive at spl6!
674 * Make sure any privious write has ended...
676 while (k
->k_sendp
!= NULL
)
677 tsleep((void *)&k
->k_sendp
, TTOPRI
, "kbd_write1", 0);
680 * If the KBD-acia is not currently busy, send the first
683 KBD
->ac_cs
= (k
->k_soft_cs
|= A_TXINT
);
684 if (KBD
->ac_cs
& A_TXRDY
) {
690 * If we're not yet done, wait until all characters are send.
695 tsleep((void *)&k
->k_send_cnt
, TTOPRI
, "kbd_write2", 0);
700 * Wakeup all procs waiting for us.
702 wakeup((void *)&k
->k_sendp
);
706 * Setup softc-fields to assemble a keyboard package.
709 kbd_pkg_start(struct kbd_softc
*kp
, uint8_t msg_start
)
713 kp
->k_package
[0] = msg_start
;
716 kp
->k_pkg_type
= KBD_MEM_PKG
;
720 kp
->k_pkg_type
= KBD_AMS_PKG
;
727 kp
->k_pkg_type
= KBD_RMS_PKG
;
731 kp
->k_pkg_type
= KBD_CLK_PKG
;
735 kp
->k_pkg_type
= KBD_JOY0_PKG
;
739 kp
->k_pkg_type
= KBD_JOY1_PKG
;
743 printf("kbd: Unknown packet 0x%x\n", msg_start
);
750 * Modifier processing
753 kbd_do_modifier(uint8_t code
)
757 up
= KBD_RELEASED(code
);
760 switch (KBD_SCANCODE(code
)) {
762 mask
= KBD_MOD_LSHIFT
;
764 case KBD_RIGHT_SHIFT
:
765 mask
= KBD_MOD_RSHIFT
;
774 /* CAPSLOCK is a toggle */
776 kbd_modifier
^= KBD_MOD_CAPS
;
781 kbd_modifier
&= ~mask
;
783 kbd_modifier
|= mask
;
792 * These are the callback functions that are passed to wscons.
793 * They really don't do anything worth noting, just call the
794 * other functions above.
798 kbd_enable(void *c
, int on
)
801 /* Wonder what this is supposed to do... */
806 kbd_set_leds(void *c
, int leds
)
809 /* we can not set the leds */
813 kbd_ioctl(void *c
, u_long cmd
, void *data
, int flag
, struct lwp
*p
)
815 struct wskbd_bell_data
*kd
;
818 case WSKBDIO_COMPLEXBELL
:
819 kd
= (struct wskbd_bell_data
*)data
;
820 kbd_bell(0, kd
->pitch
, kd
->period
, kd
->volume
);
822 case WSKBDIO_SETLEDS
:
824 case WSKBDIO_GETLEDS
:
828 *(u_int
*)data
= WSKBD_TYPE_ATARI
;
833 * We are supposed to return EPASSTHROUGH to wscons if we didn't
840 kbd_getc(void *c
, u_int
*type
, int *data
)
845 *data
= KBD_SCANCODE(key
);
846 *type
= KBD_RELEASED(key
) ? WSCONS_EVENT_KEY_UP
: WSCONS_EVENT_KEY_DOWN
;
850 kbd_pollc(void *c
, int on
)
853 kbd_softc
.k_pollingmode
= on
;
857 kbd_bell(void *v
, u_int pitch
, u_int duration
, u_int volume
)
860 kbd_bell_sparms(volume
, pitch
, duration
);