1/* $NetBSD: dzkbd.c,v 1.22 2009/05/12 12:11:54 cegger 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.22 2009/05/12 12:11:54 cegger 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 74struct dzkbd_internal { 75 struct dz_linestate *dzi_ls; 76 struct lk201_state dzi_ks; 77}; 78 79struct dzkbd_internal dzkbd_console_internal; 80 81struct dzkbd_softc { 82 struct device dzkbd_dev; /* required first: base device */ 83 84 struct dzkbd_internal *sc_itl; 85 86 int sc_enabled; 87 int kbd_type; 88 89 device_t sc_wskbddev; 90}; 91 92static int dzkbd_input(void *, int); 93 94static int dzkbd_match(device_t, cfdata_t, void *); 95static void dzkbd_attach(device_t, device_t, void *); 96 97CFATTACH_DECL(dzkbd, sizeof(struct dzkbd_softc), 98 dzkbd_match, dzkbd_attach, NULL, NULL); 99 100static int dzkbd_enable(void *, int); 101static void dzkbd_set_leds(void *, int); 102static int dzkbd_ioctl(void *, u_long, void *, int, struct lwp *); 103 104const struct wskbd_accessops dzkbd_accessops = { 105 dzkbd_enable, 106 dzkbd_set_leds, 107 dzkbd_ioctl, 108}; 109 110static void dzkbd_cngetc(void *, u_int *, int *); 111static void dzkbd_cnpollc(void *, int); 112 113const struct wskbd_consops dzkbd_consops = { 114 dzkbd_cngetc, 115 dzkbd_cnpollc, 116}; 117 118static int dzkbd_sendchar(void *, u_char); 119 120const struct wskbd_mapdata dzkbd_keymapdata = { 121 lkkbd_keydesctab, 122#ifdef DZKBD_LAYOUT 123 DZKBD_LAYOUT, 124#else 125 KB_US | KB_LK401, 126#endif 127}; 128 129/* 130 * kbd_match: how is this dz line configured? 131 */ 132static int 133dzkbd_match(device_t parent, cfdata_t cf, void *aux) 134{ 135 struct dzkm_attach_args *daa = aux; 136 137 /* Exact match is better than wildcard. */ 138 if (cf->cf_loc[DZCF_LINE] == daa->daa_line) 139 return 2; 140 141 /* This driver accepts wildcard. */ 142 if (cf->cf_loc[DZCF_LINE] == DZCF_LINE_DEFAULT) 143 return 1; 144 145 return 0; 146} 147 148static void 149dzkbd_attach(device_t parent, device_t self, void *aux) 150{ 151 struct dz_softc *dz = device_private(parent); 152 struct dzkbd_softc *dzkbd = device_private(self); 153 struct dzkm_attach_args *daa = aux; 154 struct dz_linestate *ls; 155 struct dzkbd_internal *dzi; 156 struct wskbddev_attach_args a; 157 int isconsole; 158 159 dz->sc_dz[daa->daa_line].dz_catch = dzkbd_input; 160 dz->sc_dz[daa->daa_line].dz_private = dzkbd; 161 ls = &dz->sc_dz[daa->daa_line]; 162 163 isconsole = (daa->daa_flags & DZKBD_CONSOLE); 164 165 if (isconsole) { 166 dzi = &dzkbd_console_internal; 167 } else { 168 dzi = malloc(sizeof(struct dzkbd_internal), 169 M_DEVBUF, M_NOWAIT); 170 dzi->dzi_ks.attmt.sendchar = dzkbd_sendchar; 171 dzi->dzi_ks.attmt.cookie = ls; 172 } 173 dzi->dzi_ls = ls; 174 dzkbd->sc_itl = dzi; 175 176 printf("\n"); 177 178 if (!isconsole) { 179 DELAY(100000); 180 lk201_init(&dzi->dzi_ks); 181 } 182 183 /* XXX should identify keyboard ID here XXX */ 184 /* XXX layout and the number of LED is varying XXX */ 185 186 dzkbd->kbd_type = WSKBD_TYPE_LK201; 187 188 dzkbd->sc_enabled = 1; 189 190 a.console = isconsole; 191 a.keymap = &dzkbd_keymapdata; 192 a.accessops = &dzkbd_accessops; 193 a.accesscookie = dzkbd; 194 195 dzkbd->sc_wskbddev = config_found(self, &a, wskbddevprint); 196} 197 198int 199dzkbd_cnattach(struct dz_linestate *ls) 200{ 201 202 dzkbd_console_internal.dzi_ks.attmt.sendchar = dzkbd_sendchar; 203 dzkbd_console_internal.dzi_ks.attmt.cookie = ls; 204 lk201_init(&dzkbd_console_internal.dzi_ks); 205 dzkbd_console_internal.dzi_ls = ls; 206 207 wskbd_cnattach(&dzkbd_consops, &dzkbd_console_internal, 208 &dzkbd_keymapdata); 209 210 return 0; 211} 212 213static int 214dzkbd_enable(void *v, int on) 215{ 216 struct dzkbd_softc *sc = v; 217 218 sc->sc_enabled = on; 219 return 0; 220} 221 222static int 223dzkbd_sendchar(void *v, u_char c) 224{ 225 struct dz_linestate *ls = v; 226 int s; 227 228 s = spltty(); 229 dzputc(ls, c); 230 splx(s); 231 return (0); 232} 233 234static void 235dzkbd_cngetc(void *v, u_int *type, int *data) 236{ 237 struct dzkbd_internal *dzi = v; 238 int c; 239 240 do { 241 c = dzgetc(dzi->dzi_ls); 242 } while (!lk201_decode(&dzi->dzi_ks, c, type, data)); 243} 244 245static void 246dzkbd_cnpollc(void *v, int on) 247{ 248#if 0 249 struct dzkbd_internal *dzi = v; 250#endif 251} 252 253static void 254dzkbd_set_leds(void *v, int leds) 255{ 256 struct dzkbd_softc *sc = (struct dzkbd_softc *)v; 257 258//printf("dzkbd_set_leds\n"); 259 lk201_set_leds(&sc->sc_itl->dzi_ks, leds); 260} 261 262static int 263dzkbd_ioctl(void *v, u_long cmd, void *data, int flag, struct lwp *l) 264{ 265 struct dzkbd_softc *sc = (struct dzkbd_softc *)v; 266 267 switch (cmd) { 268 case WSKBDIO_GTYPE: 269 *(int *)data = sc->kbd_type; 270 return 0; 271 case WSKBDIO_SETLEDS: 272 lk201_set_leds(&sc->sc_itl->dzi_ks, *(int *)data); 273 return 0; 274 case WSKBDIO_GETLEDS: 275 /* XXX don't dig in kbd internals */ 276 *(int *)data = sc->sc_itl->dzi_ks.leds_state; 277 return 0; 278 case WSKBDIO_COMPLEXBELL: 279 lk201_bell(&sc->sc_itl->dzi_ks, 280 (struct wskbd_bell_data *)data); 281 return 0; 282 case WSKBDIO_SETKEYCLICK: 283 lk201_set_keyclick(&sc->sc_itl->dzi_ks, *(int *)data); 284 return 0; 285 case WSKBDIO_GETKEYCLICK: 286 /* XXX don't dig in kbd internals */ 287 *(int *)data = sc->sc_itl->dzi_ks.kcvol; 288 return 0; 289 } 290 return (EPASSTHROUGH); 291} 292 293static int 294dzkbd_input(void *v, int data) 295{ 296 struct dzkbd_softc *sc = (struct dzkbd_softc *)v; 297 u_int type; 298 int val; 299 300 if (sc->sc_enabled == 0) 301 return(0); 302 303 if (lk201_decode(&sc->sc_itl->dzi_ks, data, &type, &val)) 304 wskbd_input(sc->sc_wskbddev, type, val); 305 return(1); 306} 307 308