dzkbd.c revision 1.4 1 /* $NetBSD: dzkbd.c,v 1.4 2001/11/13 12:49:45 lukem 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.4 2001/11/13 12:49:45 lukem 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/qbus/dzreg.h>
70 #include <dev/qbus/dzvar.h>
71
72 #include <dev/dec/dzkbdvar.h>
73 #include <dev/dec/lk201reg.h>
74 #include <dev/dec/lk201var.h>
75
76 #include "locators.h"
77
78 struct dzkbd_internal {
79 struct dz_linestate *dzi_ls;
80 struct lk201_state dzi_ks;
81 };
82
83 struct dzkbd_internal dzkbd_console_internal;
84
85 struct dzkbd_softc {
86 struct device dzkbd_dev; /* required first: base device */
87
88 struct dzkbd_internal *sc_itl;
89
90 int sc_enabled;
91 int kbd_type;
92
93 struct device *sc_wskbddev;
94 };
95
96 static int dzkbd_input __P((void *, int));
97
98 static int dzkbd_match __P((struct device *, struct cfdata *, void *));
99 static void dzkbd_attach __P((struct device *, struct device *, void *));
100
101 struct cfattach dzkbd_ca = {
102 sizeof(struct dzkbd_softc), dzkbd_match, dzkbd_attach,
103 };
104
105 static int dzkbd_enable __P((void *, int));
106 static void dzkbd_set_leds __P((void *, int));
107 static int dzkbd_ioctl __P((void *, u_long, caddr_t, int, struct proc *));
108
109 const struct wskbd_accessops dzkbd_accessops = {
110 dzkbd_enable,
111 dzkbd_set_leds,
112 dzkbd_ioctl,
113 };
114
115 static void dzkbd_cngetc(void *, u_int *, int *);
116 static void dzkbd_cnpollc(void *, int);
117
118 const struct wskbd_consops dzkbd_consops = {
119 dzkbd_cngetc,
120 dzkbd_cnpollc,
121 };
122
123 static int dzkbd_sendchar __P((void *, u_char));
124
125 const struct wskbd_mapdata dzkbd_keymapdata = {
126 zskbd_keydesctab,
127 #ifdef DZKBD_LAYOUT
128 DZKBD_LAYOUT,
129 #else
130 KB_US | KB_LK401,
131 #endif
132 };
133
134 /*
135 * kbd_match: how is this dz line configured?
136 */
137 static int
138 dzkbd_match(struct device *parent, struct cfdata *cf, void *aux)
139 {
140 struct dzkm_attach_args *daa = aux;
141
142 /* Exact match is better than wildcard. */
143 if (cf->cf_loc[DZCF_LINE] == daa->daa_line)
144 return 2;
145
146 /* This driver accepts wildcard. */
147 if (cf->cf_loc[DZCF_LINE] == DZCF_LINE_DEFAULT)
148 return 1;
149
150 return 0;
151 }
152
153 static void
154 dzkbd_attach(struct device *parent, struct device *self, void *aux)
155 {
156 struct dz_softc *dz = (void *)parent;
157 struct dzkbd_softc *dzkbd = (void *)self;
158 struct dzkm_attach_args *daa = aux;
159 struct dz_linestate *ls;
160 struct dzkbd_internal *dzi;
161 struct wskbddev_attach_args a;
162 int isconsole;
163
164 dz->sc_dz[daa->daa_line].dz_catch = dzkbd_input;
165 dz->sc_dz[daa->daa_line].dz_private = dzkbd;
166 ls = &dz->sc_dz[daa->daa_line];
167
168 isconsole = (daa->daa_flags & DZKBD_CONSOLE);
169
170 if (isconsole) {
171 dzi = &dzkbd_console_internal;
172 } else {
173 dzi = malloc(sizeof(struct dzkbd_internal),
174 M_DEVBUF, M_NOWAIT);
175 dzi->dzi_ks.attmt.sendchar = dzkbd_sendchar;
176 dzi->dzi_ks.attmt.cookie = ls;
177 dzi->dzi_ls = ls;
178 }
179 dzkbd->sc_itl = dzi;
180
181 printf("\n");
182
183 if (!isconsole)
184 lk201_init(&dzi->dzi_ks);
185
186 /* XXX should identify keyboard ID here XXX */
187 /* XXX layout and the number of LED is varying XXX */
188
189 dzkbd->kbd_type = WSKBD_TYPE_LK201;
190
191 dzkbd->sc_enabled = 1;
192
193 a.console = isconsole;
194 a.keymap = &dzkbd_keymapdata;
195 a.accessops = &dzkbd_accessops;
196 a.accesscookie = dzkbd;
197
198 dzkbd->sc_wskbddev = config_found(self, &a, wskbddevprint);
199 }
200
201 int
202 dzkbd_cnattach(ls)
203 struct dz_linestate *ls;
204 {
205
206 dzkbd_console_internal.dzi_ks.attmt.sendchar = dzkbd_sendchar;
207 dzkbd_console_internal.dzi_ks.attmt.cookie = ls;
208 lk201_init(&dzkbd_console_internal.dzi_ks);
209 dzkbd_console_internal.dzi_ls = ls;
210
211 wskbd_cnattach(&dzkbd_consops, &dzkbd_console_internal,
212 &dzkbd_keymapdata);
213
214 return 0;
215 }
216
217 static int
218 dzkbd_enable(v, on)
219 void *v;
220 int on;
221 {
222 struct dzkbd_softc *sc = v;
223
224 sc->sc_enabled = on;
225 return 0;
226 }
227
228 static int
229 dzkbd_sendchar(v, c)
230 void *v;
231 u_char c;
232 {
233 struct dz_linestate *ls = v;
234 int s;
235
236 s = spltty();
237 dzputc(ls, c);
238 splx(s);
239 return (0);
240 }
241
242 static void
243 dzkbd_cngetc(v, type, data)
244 void *v;
245 u_int *type;
246 int *data;
247 {
248 struct dzkbd_internal *dzi = v;
249 int c;
250
251 do {
252 c = dzgetc(dzi->dzi_ls);
253 } while (!lk201_decode(&dzi->dzi_ks, c, type, data));
254 }
255
256 static void
257 dzkbd_cnpollc(v, on)
258 void *v;
259 int on;
260 {
261 #if 0
262 struct dzkbd_internal *dzi = v;
263 #endif
264 }
265
266 static void
267 dzkbd_set_leds(v, leds)
268 void *v;
269 int leds;
270 {
271 struct dzkbd_softc *sc = (struct dzkbd_softc *)v;
272
273 //printf("dzkbd_set_leds\n");
274 lk201_set_leds(&sc->sc_itl->dzi_ks, leds);
275 }
276
277 static int
278 dzkbd_ioctl(v, cmd, data, flag, p)
279 void *v;
280 u_long cmd;
281 caddr_t data;
282 int flag;
283 struct proc *p;
284 {
285 struct dzkbd_softc *sc = (struct dzkbd_softc *)v;
286
287 switch (cmd) {
288 case WSKBDIO_GTYPE:
289 *(int *)data = sc->kbd_type;
290 return 0;
291 case WSKBDIO_SETLEDS:
292 lk201_set_leds(&sc->sc_itl->dzi_ks, *(int *)data);
293 return 0;
294 case WSKBDIO_GETLEDS:
295 /* XXX don't dig in kbd internals */
296 *(int *)data = sc->sc_itl->dzi_ks.leds_state;
297 return 0;
298 case WSKBDIO_COMPLEXBELL:
299 lk201_bell(&sc->sc_itl->dzi_ks,
300 (struct wskbd_bell_data *)data);
301 return 0;
302 case WSKBDIO_SETKEYCLICK:
303 lk201_set_keyclick(&sc->sc_itl->dzi_ks, *(int *)data);
304 return 0;
305 case WSKBDIO_GETKEYCLICK:
306 /* XXX don't dig in kbd internals */
307 *(int *)data = sc->sc_itl->dzi_ks.kcvol;
308 return 0;
309 }
310 return -1;
311 }
312
313 static int
314 dzkbd_input(v, data)
315 void *v;
316 int data;
317 {
318 struct dzkbd_softc *sc = (struct dzkbd_softc *)v;
319 u_int type;
320 int val;
321
322 if (sc->sc_enabled == 0)
323 return(0);
324
325 if (lk201_decode(&sc->sc_itl->dzi_ks, data, &type, &val))
326 wskbd_input(sc->sc_wskbddev, type, val);
327 return(1);
328 }
329
330