1 /* $NetBSD: kbd_zs.c,v 1.22 2008/03/29 19:15:36 tsutsui 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 zs channel.
45 * This driver uses kbdsun middle layer to hook up to /dev/kbd.
49 * Zilog Z8530 Dual UART driver (keyboard interface)
51 * This is the 8530 portion of the driver that will be attached to
52 * the "zsc" driver for a Sun keyboard.
55 #include <sys/cdefs.h>
56 __KERNEL_RCSID(0, "$NetBSD: kbd_zs.c,v 1.22 2008/03/29 19:15:36 tsutsui Exp $");
58 #include <sys/param.h>
59 #include <sys/systm.h>
61 #include <sys/device.h>
62 #include <sys/kernel.h>
63 #include <sys/malloc.h>
65 #include <sys/signal.h>
66 #include <sys/signalvar.h>
68 #include <sys/select.h>
69 #include <sys/syslog.h>
71 #include <dev/ic/z8530reg.h>
72 #include <machine/z8530var.h>
73 #include <dev/sun/vuid_event.h>
74 #include <dev/sun/event_var.h>
75 #include <dev/sun/kbd_reg.h>
76 #include <dev/sun/kbd_xlate.h>
77 #include <dev/sun/kbdvar.h>
78 #include <dev/sun/kbdsunvar.h>
81 void kbd_wskbd_attach(struct kbd_softc
*k
, int isconsole
);
84 /****************************************************************
85 * Interface to the lower layer (zscc)
86 ****************************************************************/
88 static void kbd_zs_rxint(struct zs_chanstate
*);
89 static void kbd_zs_stint(struct zs_chanstate
*, int);
90 static void kbd_zs_txint(struct zs_chanstate
*);
91 static void kbd_zs_softint(struct zs_chanstate
*);
93 struct zsops zsops_kbd
= {
94 kbd_zs_rxint
, /* receive char available */
95 kbd_zs_stint
, /* external/status */
96 kbd_zs_txint
, /* xmit buffer empty */
97 kbd_zs_softint
, /* process software interrupt */
100 static int kbd_zs_match(device_t
, cfdata_t
, void *);
101 static void kbd_zs_attach(device_t
, device_t
, void *);
102 static void kbd_zs_write_data(struct kbd_sun_softc
*, int);
104 CFATTACH_DECL_NEW(kbd_zs
, sizeof(struct kbd_sun_softc
),
105 kbd_zs_match
, kbd_zs_attach
, NULL
, NULL
);
107 /* Fall-back baud rate */
108 int kbd_zs_bps
= KBD_DEFAULT_BPS
;
111 * kbd_zs_match: how is this zs channel configured?
114 kbd_zs_match(device_t parent
, cfdata_t cf
, void *aux
)
116 struct zsc_attach_args
*args
= aux
;
118 /* Exact match required for keyboard. */
119 if (cf
->cf_loc
[ZSCCF_CHANNEL
] == args
->channel
)
126 kbd_zs_attach(device_t parent
, device_t self
, void *aux
)
128 struct kbd_sun_softc
*k
= device_private(self
);
129 struct zsc_softc
*zsc
= device_private(parent
);
130 struct zsc_attach_args
*args
= aux
;
131 struct zs_chanstate
*cs
;
136 k
->k_kbd
.k_dev
= self
;
138 /* provide upper layer with a link to the middle layer */
139 k
->k_kbd
.k_ops
= &kbd_ops_sun
;
141 /* provide middle layer with a link to the lower layer (i.e. us) */
142 channel
= args
->channel
;
143 cs
= zsc
->zsc_cs
[channel
];
145 cs
->cs_ops
= &zsops_kbd
;
147 k
->k_write_data
= kbd_zs_write_data
;
149 if ((bps
= cs
->cs_defspeed
) == 0)
152 aprint_normal(": baud rate %d", bps
);
154 if ((args
->hwflags
& ZS_HWFLAG_CONSOLE_INPUT
) != 0) {
156 * Hookup ourselves as the console input channel
158 struct cons_channel
*cc
= kbd_cc_alloc(&k
->k_kbd
);
163 cons_attach_input(cc
, args
->consdev
);
164 k
->k_kbd
.k_isconsole
= 1;
165 aprint_normal(" (console input)");
169 /* Initialize the speed, etc. */
171 if (k
->k_kbd
.k_isconsole
== 0) {
172 /* Not the console; may need reset. */
173 reset
= (channel
== 0) ?
174 ZSWR9_A_RESET
: ZSWR9_B_RESET
;
175 zs_write_reg(cs
, 9, reset
);
177 /* These are OK as set by zscc: WR3, WR4, WR5 */
178 /* We don't care about status interrupts. */
179 cs
->cs_preg
[1] = ZSWR1_RIE
| ZSWR1_TIE
;
180 (void) zs_set_speed(cs
, bps
);
181 zs_loadchannelregs(cs
);
184 /* Do this before any calls to kbd_rint(). */
185 kbd_xlate_init(&k
->k_kbd
.k_state
);
187 /* Magic sequence. */
188 k
->k_magic1
= KBD_L1
;
191 kbd_wskbd_attach(&k
->k_kbd
, k
->k_kbd
.k_isconsole
);
196 * used by kbd_sun_start_tx();
199 kbd_zs_write_data(struct kbd_sun_softc
*k
, int c
)
203 /* Need splzs to avoid interruption of the delay. */
205 zs_write_data(k
->k_cs
, c
);
210 kbd_zs_rxint(struct zs_chanstate
*cs
)
212 struct kbd_sun_softc
*k
;
220 * First read the status, because reading the received char
221 * destroys the status of this char.
223 rr1
= zs_read_reg(cs
, 1);
224 c
= zs_read_data(cs
);
226 if (rr1
& (ZSRR1_FE
| ZSRR1_DO
| ZSRR1_PE
)) {
227 /* Clear the receive error. */
228 zs_write_csr(cs
, ZSWR0_RESET_ERRORS
);
232 * Check NOW for a console abort sequence, so that we can
233 * abort even when interrupts are locking up the machine.
235 if (k
->k_magic1_down
) {
236 /* The last keycode was "MAGIC1" down. */
237 k
->k_magic1_down
= 0;
238 if (c
== k
->k_magic2
) {
239 /* Magic "L1-A" sequence; enter debugger. */
240 if (k
->k_kbd
.k_isconsole
) {
242 /* Debugger done. Fake L1-up to finish it. */
243 c
= k
->k_magic1
| KBD_UP
;
245 printf("%s: magic sequence, but not console\n",
246 device_xname(k
->k_kbd
.k_dev
));
250 if (c
== k
->k_magic1
) {
251 k
->k_magic1_down
= 1;
254 k
->k_rbuf
[put
] = (c
<< 8) | rr1
;
255 put_next
= (put
+ 1) & KBD_RX_RING_MASK
;
257 /* Would overrun if increment makes (put==get). */
258 if (put_next
== k
->k_rbget
) {
259 k
->k_intr_flags
|= INTR_RX_OVERRUN
;
261 /* OK, really increment. */
268 /* Ask for softint() call. */
274 kbd_zs_txint(struct zs_chanstate
*cs
)
276 struct kbd_sun_softc
*k
;
279 zs_write_csr(cs
, ZSWR0_RESET_TXINT
);
280 k
->k_intr_flags
|= INTR_TX_EMPTY
;
281 /* Ask for softint() call. */
287 kbd_zs_stint(struct zs_chanstate
*cs
, int force
)
289 struct kbd_sun_softc
*k
;
294 rr0
= zs_read_csr(cs
);
295 zs_write_csr(cs
, ZSWR0_RESET_STATUS
);
298 if (rr0
& ZSRR0_BREAK
) {
299 /* Keyboard unplugged? */
306 * We have to accumulate status line changes here.
307 * Otherwise, if we get multiple status interrupts
308 * before the softint runs, we could fail to notice
309 * some status line changes in the softint routine.
310 * Fix from Bill Studenmund, October 1996.
312 cs
->cs_rr0_delta
|= (cs
->cs_rr0
^ rr0
);
314 k
->k_intr_flags
|= INTR_ST_CHECK
;
316 /* Ask for softint() call. */
321 * Get input from the receive ring and pass it on.
322 * Note: this is called at splsoftclock()
325 kbd_zs_softint(struct zs_chanstate
*cs
)
327 struct kbd_sun_softc
*k
;
334 /* Atomically get and clear flags. */
336 intr_flags
= k
->k_intr_flags
;
339 /* Now lower to spltty for the rest. */
343 * Copy data from the receive ring to the event layer.
346 while (get
!= k
->k_rbput
) {
347 ring_data
= k
->k_rbuf
[get
];
348 get
= (get
+ 1) & KBD_RX_RING_MASK
;
350 /* low byte of ring_data is rr1 */
351 c
= (ring_data
>> 8) & 0xff;
353 if (ring_data
& ZSRR1_DO
)
354 intr_flags
|= INTR_RX_OVERRUN
;
355 if (ring_data
& (ZSRR1_FE
| ZSRR1_PE
)) {
357 * After garbage, flush pending input, and
358 * send a reset to resync key translation.
360 log(LOG_ERR
, "%s: input error (0x%x)\n",
361 device_xname(k
->k_kbd
.k_dev
), ring_data
);
362 get
= k
->k_rbput
; /* flush */
366 /* Pass this up to the "middle" layer. */
369 if (intr_flags
& INTR_RX_OVERRUN
) {
370 log(LOG_ERR
, "%s: input overrun\n",
371 device_xname(k
->k_kbd
.k_dev
));
373 /* Send a reset to resync translation. */
374 kbd_sun_output(k
, KBD_CMD_RESET
);
379 if (intr_flags
& INTR_TX_EMPTY
) {
381 * Transmit done. Try to send more, or
382 * clear busy and wakeup drain waiters.
384 k
->k_txflags
&= ~K_TXBUSY
;
388 if (intr_flags
& INTR_ST_CHECK
) {
390 * Status line change. (Not expected.)
392 log(LOG_ERR
, "%s: status interrupt?\n",
393 device_xname(k
->k_kbd
.k_dev
));
394 cs
->cs_rr0_delta
= 0;