1 /* $NetBSD: sunkbd.c,v 1.26 2007/11/10 18:00:11 ad Exp $ */
4 * Copyright (c) 1992, 1993
5 * The Regents of the University of California. All rights reserved.
7 * This software was developed by the Computer Systems Engineering group
8 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
9 * contributed to Berkeley.
11 * All advertising materials mentioning features or use of this software
12 * must display the following acknowledgement:
13 * This product includes software developed by the University of
14 * California, Lawrence Berkeley Laboratory.
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
19 * 1. Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution.
24 * 3. Neither the name of the University nor the names of its contributors
25 * may be used to endorse or promote products derived from this software
26 * without specific prior written permission.
28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40 * @(#)kbd.c 8.2 (Berkeley) 10/30/93
44 * /dev/kbd lower layer for sun keyboard off a tty (line discipline).
45 * This driver uses kbdsun middle layer to hook up to /dev/kbd.
49 * Keyboard interface line discipline.
53 #include <sys/cdefs.h>
54 __KERNEL_RCSID(0, "$NetBSD: sunkbd.c,v 1.26 2007/11/10 18:00:11 ad Exp $");
56 #include <sys/param.h>
57 #include <sys/systm.h>
59 #include <sys/device.h>
60 #include <sys/kernel.h>
61 #include <sys/malloc.h>
63 #include <sys/signal.h>
64 #include <sys/signalvar.h>
66 #include <sys/select.h>
67 #include <sys/syslog.h>
68 #include <sys/fcntl.h>
72 #include <machine/vuid_event.h>
73 #include <machine/kbd.h>
74 #include <dev/sun/event_var.h>
75 #include <dev/sun/kbd_xlate.h>
76 #include <dev/sun/kbdvar.h>
77 #include <dev/sun/kbdsunvar.h>
78 #include <dev/sun/kbd_ms_ttyvar.h>
80 /****************************************************************
81 * Interface to the lower layer (ttycc)
82 ****************************************************************/
84 static int sunkbd_match(device_t
, cfdata_t
, void *);
85 static void sunkbd_attach(device_t
, device_t
, void *);
86 static void sunkbd_write_data(struct kbd_sun_softc
*, int);
87 static int sunkbdiopen(device_t
, int mode
);
90 void kbd_wskbd_attach(struct kbd_softc
*k
, int isconsole
);
93 int sunkbdinput(int, struct tty
*);
94 int sunkbdstart(struct tty
*);
96 /* Default keyboard baud rate */
97 int sunkbd_bps
= KBD_DEFAULT_BPS
;
99 CFATTACH_DECL_NEW(kbd_tty
, sizeof(struct kbd_sun_softc
),
100 sunkbd_match
, sunkbd_attach
, NULL
, NULL
);
102 struct linesw sunkbd_disc
= {
105 .l_close
= ttylclose
,
108 .l_ioctl
= ttynullioctl
,
109 .l_rint
= sunkbdinput
,
110 .l_start
= sunkbdstart
,
111 .l_modem
= nullmodem
,
117 * sunkbd_match: how is this tty channel configured?
120 sunkbd_match(device_t parent
, cfdata_t cf
, void *aux
)
122 struct kbd_ms_tty_attach_args
*args
= aux
;
124 if (strcmp(args
->kmta_name
, "keyboard") == 0)
131 sunkbd_attach(device_t parent
, device_t self
, void *aux
)
133 struct kbd_sun_softc
*k
= device_private(self
);
134 struct kbd_ms_tty_attach_args
*args
= aux
;
135 struct tty
*tp
= args
->kmta_tp
;
136 struct cons_channel
*cc
;
138 k
->k_kbd
.k_dev
= self
;
140 /* Set up the proper line discipline. */
141 if (ttyldisc_attach(&sunkbd_disc
) != 0)
142 panic("sunkbd_attach: sunkbd_disc");
143 ttyldisc_release(tp
->t_linesw
);
144 tp
->t_linesw
= ttyldisc_lookup(sunkbd_disc
.l_name
);
145 KASSERT(tp
->t_linesw
== &sunkbd_disc
);
146 tp
->t_oflag
&= ~OPOST
;
147 tp
->t_dev
= args
->kmta_dev
;
149 /* link the structures together. */
153 /* provide our middle layer with a link to the lower layer (i.e. us) */
154 k
->k_deviopen
= sunkbdiopen
;
155 k
->k_deviclose
= NULL
;
156 k
->k_write_data
= sunkbd_write_data
;
158 /* provide upper layer with a link to our middle layer */
159 k
->k_kbd
.k_ops
= &kbd_ops_sun
;
161 /* alloc console input channel */
162 if ((cc
= kbd_cc_alloc(&k
->k_kbd
)) == NULL
)
165 if (args
->kmta_consdev
) {
169 * Hookup ourselves as the console input channel
171 args
->kmta_baud
= sunkbd_bps
;
172 args
->kmta_cflag
= CLOCAL
|CS8
;
173 cons_attach_input(cc
, args
->kmta_consdev
);
175 /* Tell our parent what the console should be. */
176 args
->kmta_consdev
= cn_tab
;
177 k
->k_kbd
.k_isconsole
= 1;
178 aprint_normal(" (console input)");
180 /* Set magic to "L1-A" */
186 extern void kd_attach_input(struct cons_channel
*);
195 kbd_wskbd_attach(&k
->k_kbd
, args
->kmta_consdev
!= NULL
);
198 /* Do this before any calls to kbd_rint(). */
199 kbd_xlate_init(&k
->k_kbd
.k_state
);
201 /* Magic sequence. */
202 k
->k_magic1
= KBD_L1
;
207 * Internal open routine. This really should be inside com.c
208 * But I'm putting it here until we have a generic internal open
212 sunkbdiopen(device_t dev
, int flags
)
214 struct kbd_sun_softc
*k
= device_private(dev
);
215 struct tty
*tp
= k
->k_priv
;
216 struct lwp
*l
= curlwp
? curlwp
: &lwp0
;
220 /* Open the lower device */
221 if ((error
= cdev_open(tp
->t_dev
, O_NONBLOCK
|flags
,
222 0/* ignored? */, l
)) != 0)
225 /* Now configure it for the console. */
227 t
.c_ispeed
= sunkbd_bps
;
228 t
.c_ospeed
= sunkbd_bps
;
229 t
.c_cflag
= CLOCAL
|CS8
;
230 (*tp
->t_param
)(tp
, &t
);
236 * TTY interface to handle input.
239 sunkbdinput(int c
, struct tty
*tp
)
241 struct kbd_sun_softc
*k
= tp
->t_sc
;
248 * Handle exceptional conditions (break, parity, framing).
250 if ((error
= ((c
& TTY_ERRORMASK
))) != 0) {
252 * After garbage, flush pending input, and
253 * send a reset to resync key translation.
255 log(LOG_ERR
, "%s: input error (0x%x)\n",
256 device_xname(k
->k_kbd
.k_dev
), c
);
258 if (!k
->k_txflags
& K_TXBUSY
) {
259 ttyflush(tp
, FREAD
| FWRITE
);
265 * Check for input buffer overflow
267 if (tp
->t_rawq
.c_cc
+ tp
->t_canq
.c_cc
>= TTYHOG
) {
268 log(LOG_ERR
, "%s: input overrun\n",
269 device_xname(k
->k_kbd
.k_dev
));
273 /* Pass this up to the "middle" layer. */
274 return(kbd_sun_input(k
, c
));
277 /* Send a reset to resync translation. */
278 kbd_sun_output(k
, KBD_CMD_RESET
);
279 return (ttstart(tp
));
284 sunkbdstart(struct tty
*tp
)
286 struct kbd_sun_softc
*k
= tp
->t_sc
;
289 * Transmit done. Try to send more, or
290 * clear busy and wakeup drain waiters.
292 k
->k_txflags
&= ~K_TXBUSY
;
298 * used by kbd_sun_start_tx();
301 sunkbd_write_data(struct kbd_sun_softc
*k
, int c
)
303 struct tty
*tp
= k
->k_priv
;
305 mutex_spin_enter(&tty_lock
);
308 mutex_spin_exit(&tty_lock
);