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