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