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