1 /* $NetBSD: dzkbd.c,v 1.35 2025/04/06 03:36:13 riastradh 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.35 2025/04/06 03:36:13 riastradh 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 #include <sys/intr.h> 57 58 #include <dev/wscons/wsconsio.h> 59 #include <dev/wscons/wskbdvar.h> 60 #include <dev/wscons/wsksymdef.h> 61 #include <dev/wscons/wsksymvar.h> 62 #include <dev/dec/wskbdmap_lk201.h> 63 64 #include <sys/bus.h> 65 66 #include <dev/dec/dzreg.h> 67 #include <dev/dec/dzvar.h> 68 #include <dev/dec/dzkbdvar.h> 69 #include <dev/dec/lk201reg.h> 70 #include <dev/dec/lk201var.h> 71 72 #include "locators.h" 73 74 struct dzkbd_internal { 75 struct dz_linestate *dzi_ls; 76 struct lk201_state dzi_ks; 77 }; 78 79 struct dzkbd_internal dzkbd_console_internal; 80 81 struct dzkbd_softc { 82 struct dzkbd_internal *sc_itl; 83 84 int sc_enabled; 85 int kbd_type; 86 87 device_t sc_wskbddev; 88 }; 89 90 static int dzkbd_input(void *, int); 91 92 static int dzkbd_match(device_t, cfdata_t, void *); 93 static void dzkbd_attach(device_t, device_t, void *); 94 95 CFATTACH_DECL_NEW(dzkbd, sizeof(struct dzkbd_softc), 96 dzkbd_match, dzkbd_attach, NULL, NULL); 97 98 static int dzkbd_enable(void *, int); 99 static void dzkbd_set_leds(void *, int); 100 static int dzkbd_ioctl(void *, u_long, void *, int, struct lwp *); 101 102 const struct wskbd_accessops dzkbd_accessops = { 103 dzkbd_enable, 104 dzkbd_set_leds, 105 dzkbd_ioctl, 106 }; 107 108 static void dzkbd_cngetc(void *, u_int *, int *); 109 static void dzkbd_cnpollc(void *, int); 110 111 const struct wskbd_consops dzkbd_consops = { 112 dzkbd_cngetc, 113 dzkbd_cnpollc, 114 }; 115 116 static int dzkbd_sendchar(void *, u_char); 117 118 const struct wskbd_mapdata dzkbd_keymapdata = { 119 lkkbd_keydesctab, 120 #ifdef DZKBD_LAYOUT 121 DZKBD_LAYOUT, 122 #else 123 KB_US | KB_LK401, 124 #endif 125 }; 126 127 /* 128 * kbd_match: how is this dz line configured? 129 */ 130 static int 131 dzkbd_match(device_t parent, cfdata_t cf, void *aux) 132 { 133 struct dzkm_attach_args *daa = aux; 134 135 /* Exact match is better than wildcard. */ 136 if (cf->cf_loc[DZCF_LINE] == daa->daa_line) 137 return 2; 138 139 /* This driver accepts wildcard. */ 140 if (cf->cf_loc[DZCF_LINE] == DZCF_LINE_DEFAULT) 141 return 1; 142 143 return 0; 144 } 145 146 static void 147 dzkbd_attach(device_t parent, device_t self, void *aux) 148 { 149 struct dz_softc *dz = device_private(parent); 150 struct dzkbd_softc *dzkbd = device_private(self); 151 struct dzkm_attach_args *daa = aux; 152 struct dz_linestate *ls; 153 struct dzkbd_internal *dzi; 154 struct wskbddev_attach_args a; 155 int isconsole; 156 157 dz->sc_dz[daa->daa_line].dz_catch = dzkbd_input; 158 dz->sc_dz[daa->daa_line].dz_private = dzkbd; 159 ls = &dz->sc_dz[daa->daa_line]; 160 161 isconsole = (daa->daa_flags & DZKBD_CONSOLE); 162 163 if (isconsole) 164 dzi = &dzkbd_console_internal; 165 else 166 dzi = malloc(sizeof(struct dzkbd_internal), M_DEVBUF, M_WAITOK); 167 168 dzi->dzi_ks.attmt.sendchar = dzkbd_sendchar; 169 dzi->dzi_ks.attmt.cookie = ls; 170 dzi->dzi_ls = ls; 171 dzkbd->sc_itl = dzi; 172 173 aprint_normal("\n"); 174 175 DELAY(100000); 176 lk201_init(&dzi->dzi_ks); 177 178 /* 179 * Set the keyboard type according to what lk201_init() 180 * detected. 181 * 182 * XXX: should also do something about the layout, which 183 * presently hardcodes LK401 layout. 184 */ 185 switch (dzi->dzi_ks.kbdtype) { 186 default: 187 case KBD_LK201: 188 dzkbd->kbd_type = WSKBD_TYPE_LK201; 189 break; 190 191 case KBD_LK401: 192 dzkbd->kbd_type = WSKBD_TYPE_LK401; 193 break; 194 } 195 196 dzkbd->sc_enabled = 1; 197 198 a.console = isconsole; 199 a.keymap = &dzkbd_keymapdata; 200 a.accessops = &dzkbd_accessops; 201 a.accesscookie = dzkbd; 202 203 dzkbd->sc_wskbddev = config_found(self, &a, wskbddevprint, CFARGS_NONE); 204 } 205 206 int 207 dzkbd_cnattach(struct dz_linestate *ls) 208 { 209 210 dzkbd_console_internal.dzi_ks.attmt.sendchar = dzkbd_sendchar; 211 dzkbd_console_internal.dzi_ks.attmt.cookie = ls; 212 lk201_init(&dzkbd_console_internal.dzi_ks); 213 dzkbd_console_internal.dzi_ls = ls; 214 215 wskbd_cnattach(&dzkbd_consops, &dzkbd_console_internal, 216 &dzkbd_keymapdata); 217 218 return 0; 219 } 220 221 static int 222 dzkbd_enable(void *v, int on) 223 { 224 struct dzkbd_softc *sc = v; 225 226 sc->sc_enabled = on; 227 return 0; 228 } 229 230 static int 231 dzkbd_sendchar(void *v, 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(void *v, u_int *type, int *data) 244 { 245 struct dzkbd_internal *dzi = v; 246 int c; 247 248 do { 249 c = dzgetc(dzi->dzi_ls); 250 } while (lk201_decode(&dzi->dzi_ks, 0, c, type, data) == LKD_NODATA); 251 } 252 253 static void 254 dzkbd_cnpollc(void *v, int on) 255 { 256 #if 0 257 struct dzkbd_internal *dzi = v; 258 #endif 259 } 260 261 static void 262 dzkbd_set_leds(void *v, int leds) 263 { 264 struct dzkbd_softc *sc = (struct dzkbd_softc *)v; 265 266 //printf("dzkbd_set_leds\n"); 267 lk201_set_leds(&sc->sc_itl->dzi_ks, leds); 268 } 269 270 static int 271 dzkbd_ioctl(void *v, u_long cmd, void *data, int flag, struct lwp *l) 272 { 273 struct dzkbd_softc *sc = (struct dzkbd_softc *)v; 274 275 switch (cmd) { 276 case WSKBDIO_GTYPE: 277 *(int *)data = sc->kbd_type; 278 return 0; 279 case WSKBDIO_SETLEDS: 280 lk201_set_leds(&sc->sc_itl->dzi_ks, *(int *)data); 281 return 0; 282 case WSKBDIO_GETLEDS: 283 /* XXX don't dig in kbd internals */ 284 *(int *)data = sc->sc_itl->dzi_ks.leds_state; 285 return 0; 286 case WSKBDIO_COMPLEXBELL: 287 lk201_bell(&sc->sc_itl->dzi_ks, 288 (struct wskbd_bell_data *)data); 289 return 0; 290 case WSKBDIO_SETKEYCLICK: 291 lk201_set_keyclick(&sc->sc_itl->dzi_ks, *(int *)data); 292 return 0; 293 case WSKBDIO_GETKEYCLICK: 294 /* XXX don't dig in kbd internals */ 295 *(int *)data = sc->sc_itl->dzi_ks.kcvol; 296 return 0; 297 } 298 return (EPASSTHROUGH); 299 } 300 301 static int 302 dzkbd_input(void *v, int data) 303 { 304 struct dzkbd_softc *sc = (struct dzkbd_softc *)v; 305 u_int type; 306 int val; 307 int decode; 308 309 do { 310 decode = lk201_decode(&sc->sc_itl->dzi_ks, 1, 311 data, &type, &val); 312 if (decode != LKD_NODATA) 313 wskbd_input(sc->sc_wskbddev, type, val); 314 } while (decode == LKD_MORE); 315 316 return(1); 317 } 318