xref: /netbsd/sys/dev/dec/dzkbd.c (revision c4a72b64)
1 /*	$NetBSD: dzkbd.c,v 1.10 2002/10/02 16:33:44 thorpej Exp $	*/
2 
3 /*
4  * Copyright (c) 1992, 1993
5  *	The Regents of the University of California.  All rights reserved.
6  *
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.
10  *
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.
15  *
16  * Redistribution and use in source and binary forms, with or without
17  * modification, are permitted provided that the following conditions
18  * are met:
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. All advertising materials mentioning features or use of this software
25  *    must display the following acknowledgement:
26  *	This product includes software developed by the University of
27  *	California, Berkeley and its contributors.
28  * 4. Neither the name of the University nor the names of its contributors
29  *    may be used to endorse or promote products derived from this software
30  *    without specific prior written permission.
31  *
32  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
33  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
34  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
35  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
36  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
40  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
41  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
42  * SUCH DAMAGE.
43  *
44  *	@(#)kbd.c	8.2 (Berkeley) 10/30/93
45  */
46 
47 /*
48  * LK200/LK400 keyboard attached to line 0 of the DZ*-11
49  */
50 
51 #include <sys/cdefs.h>
52 __KERNEL_RCSID(0, "$NetBSD: dzkbd.c,v 1.10 2002/10/02 16:33:44 thorpej Exp $");
53 
54 #include <sys/param.h>
55 #include <sys/systm.h>
56 #include <sys/device.h>
57 #include <sys/ioctl.h>
58 #include <sys/syslog.h>
59 #include <sys/malloc.h>
60 
61 #include <dev/wscons/wsconsio.h>
62 #include <dev/wscons/wskbdvar.h>
63 #include <dev/wscons/wsksymdef.h>
64 #include <dev/wscons/wsksymvar.h>
65 #include <dev/dec/wskbdmap_lk201.h>
66 
67 #include <machine/bus.h>
68 
69 #include <dev/dec/dzreg.h>
70 #include <dev/dec/dzvar.h>
71 #include <dev/dec/dzkbdvar.h>
72 #include <dev/dec/lk201reg.h>
73 #include <dev/dec/lk201var.h>
74 
75 #include "locators.h"
76 
77 struct dzkbd_internal {
78 	struct dz_linestate *dzi_ls;
79 	struct lk201_state dzi_ks;
80 };
81 
82 struct dzkbd_internal dzkbd_console_internal;
83 
84 struct dzkbd_softc {
85 	struct device dzkbd_dev;	/* required first: base device */
86 
87 	struct dzkbd_internal *sc_itl;
88 
89 	int sc_enabled;
90 	int kbd_type;
91 
92 	struct device *sc_wskbddev;
93 };
94 
95 static int	dzkbd_input __P((void *, int));
96 
97 static int	dzkbd_match __P((struct device *, struct cfdata *, void *));
98 static void	dzkbd_attach __P((struct device *, struct device *, void *));
99 
100 CFATTACH_DECL(dzkbd, sizeof(struct dzkbd_softc),
101     dzkbd_match, dzkbd_attach, NULL, NULL);
102 
103 static int	dzkbd_enable __P((void *, int));
104 static void	dzkbd_set_leds __P((void *, int));
105 static int	dzkbd_ioctl __P((void *, u_long, caddr_t, int, struct proc *));
106 
107 const struct wskbd_accessops dzkbd_accessops = {
108 	dzkbd_enable,
109 	dzkbd_set_leds,
110 	dzkbd_ioctl,
111 };
112 
113 static void	dzkbd_cngetc(void *, u_int *, int *);
114 static void	dzkbd_cnpollc(void *, int);
115 
116 const struct wskbd_consops dzkbd_consops = {
117 	dzkbd_cngetc,
118 	dzkbd_cnpollc,
119 };
120 
121 static int dzkbd_sendchar __P((void *, u_char));
122 
123 const struct wskbd_mapdata dzkbd_keymapdata = {
124 	lkkbd_keydesctab,
125 #ifdef DZKBD_LAYOUT
126 	DZKBD_LAYOUT,
127 #else
128 	KB_US | KB_LK401,
129 #endif
130 };
131 
132 /*
133  * kbd_match: how is this dz line configured?
134  */
135 static int
136 dzkbd_match(struct device *parent, struct cfdata *cf, void *aux)
137 {
138 	struct dzkm_attach_args *daa = aux;
139 
140 	/* Exact match is better than wildcard. */
141 	if (cf->cf_loc[DZCF_LINE] == daa->daa_line)
142 		return 2;
143 
144 	/* This driver accepts wildcard. */
145 	if (cf->cf_loc[DZCF_LINE] == DZCF_LINE_DEFAULT)
146 		return 1;
147 
148 	return 0;
149 }
150 
151 static void
152 dzkbd_attach(struct device *parent, struct device *self, void *aux)
153 {
154 	struct dz_softc *dz = (void *)parent;
155 	struct dzkbd_softc *dzkbd = (void *)self;
156 	struct dzkm_attach_args *daa = aux;
157 	struct dz_linestate *ls;
158 	struct dzkbd_internal *dzi;
159 	struct wskbddev_attach_args a;
160 	int isconsole;
161 
162 	dz->sc_dz[daa->daa_line].dz_catch = dzkbd_input;
163 	dz->sc_dz[daa->daa_line].dz_private = dzkbd;
164 	ls = &dz->sc_dz[daa->daa_line];
165 
166 	isconsole = (daa->daa_flags & DZKBD_CONSOLE);
167 
168 	if (isconsole) {
169 		dzi = &dzkbd_console_internal;
170 	} else {
171 		dzi = malloc(sizeof(struct dzkbd_internal),
172 				       M_DEVBUF, M_NOWAIT);
173 		dzi->dzi_ks.attmt.sendchar = dzkbd_sendchar;
174 		dzi->dzi_ks.attmt.cookie = ls;
175 		dzi->dzi_ls = ls;
176 	}
177 	dzkbd->sc_itl = dzi;
178 
179 	printf("\n");
180 
181 	if (!isconsole)
182 		lk201_init(&dzi->dzi_ks);
183 
184 	/* XXX should identify keyboard ID here XXX */
185 	/* XXX layout and the number of LED is varying XXX */
186 
187 	dzkbd->kbd_type = WSKBD_TYPE_LK201;
188 
189 	dzkbd->sc_enabled = 1;
190 
191 	a.console = isconsole;
192 	a.keymap = &dzkbd_keymapdata;
193 	a.accessops = &dzkbd_accessops;
194 	a.accesscookie = dzkbd;
195 
196 	dzkbd->sc_wskbddev = config_found(self, &a, wskbddevprint);
197 }
198 
199 int
200 dzkbd_cnattach(ls)
201 	struct dz_linestate *ls;
202 {
203 
204 	dzkbd_console_internal.dzi_ks.attmt.sendchar = dzkbd_sendchar;
205 	dzkbd_console_internal.dzi_ks.attmt.cookie = ls;
206 	lk201_init(&dzkbd_console_internal.dzi_ks);
207 	dzkbd_console_internal.dzi_ls = ls;
208 
209 	wskbd_cnattach(&dzkbd_consops, &dzkbd_console_internal,
210 		       &dzkbd_keymapdata);
211 
212 	return 0;
213 }
214 
215 static int
216 dzkbd_enable(v, on)
217 	void *v;
218 	int on;
219 {
220 	struct dzkbd_softc *sc = v;
221 
222 	sc->sc_enabled = on;
223 	return 0;
224 }
225 
226 static int
227 dzkbd_sendchar(v, c)
228 	void *v;
229 	u_char c;
230 {
231 	struct dz_linestate *ls = v;
232 	int s;
233 
234 	s = spltty();
235 	dzputc(ls, c);
236 	splx(s);
237 	return (0);
238 }
239 
240 static void
241 dzkbd_cngetc(v, type, data)
242 	void *v;
243 	u_int *type;
244 	int *data;
245 {
246 	struct dzkbd_internal *dzi = v;
247 	int c;
248 
249 	do {
250 		c = dzgetc(dzi->dzi_ls);
251 	} while (!lk201_decode(&dzi->dzi_ks, c, type, data));
252 }
253 
254 static void
255 dzkbd_cnpollc(v, on)
256 	void *v;
257         int on;
258 {
259 #if 0
260 	struct dzkbd_internal *dzi = v;
261 #endif
262 }
263 
264 static void
265 dzkbd_set_leds(v, leds)
266 	void *v;
267 	int leds;
268 {
269 	struct dzkbd_softc *sc = (struct dzkbd_softc *)v;
270 
271 //printf("dzkbd_set_leds\n");
272 	lk201_set_leds(&sc->sc_itl->dzi_ks, leds);
273 }
274 
275 static int
276 dzkbd_ioctl(v, cmd, data, flag, p)
277 	void *v;
278 	u_long cmd;
279 	caddr_t data;
280 	int flag;
281 	struct proc *p;
282 {
283 	struct dzkbd_softc *sc = (struct dzkbd_softc *)v;
284 
285 	switch (cmd) {
286 	case WSKBDIO_GTYPE:
287 		*(int *)data = sc->kbd_type;
288 		return 0;
289 	case WSKBDIO_SETLEDS:
290 		lk201_set_leds(&sc->sc_itl->dzi_ks, *(int *)data);
291 		return 0;
292 	case WSKBDIO_GETLEDS:
293 		/* XXX don't dig in kbd internals */
294 		*(int *)data = sc->sc_itl->dzi_ks.leds_state;
295 		return 0;
296 	case WSKBDIO_COMPLEXBELL:
297 		lk201_bell(&sc->sc_itl->dzi_ks,
298 			   (struct wskbd_bell_data *)data);
299 		return 0;
300 	case WSKBDIO_SETKEYCLICK:
301 		lk201_set_keyclick(&sc->sc_itl->dzi_ks, *(int *)data);
302 		return 0;
303 	case WSKBDIO_GETKEYCLICK:
304 		/* XXX don't dig in kbd internals */
305 		*(int *)data = sc->sc_itl->dzi_ks.kcvol;
306 		return 0;
307 	}
308 	return (EPASSTHROUGH);
309 }
310 
311 static int
312 dzkbd_input(v, data)
313 	void *v;
314 	int data;
315 {
316 	struct dzkbd_softc *sc = (struct dzkbd_softc *)v;
317 	u_int type;
318 	int val;
319 
320 	if (sc->sc_enabled == 0)
321 		return(0);
322 
323 	if (lk201_decode(&sc->sc_itl->dzi_ks, data, &type, &val))
324 		wskbd_input(sc->sc_wskbddev, type, val);
325 	return(1);
326 }
327 
328