dzkbd.c revision 1.10 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