Home | History | Annotate | Line # | Download | only in uba
qvkbd.c revision 1.1
      1 /*	$NetBSD: qvkbd.c,v 1.1 2015/07/05 03:07:21 matt Exp $	*/
      2 
      3 /* Copyright (c) 2015 Charles H. Dickman. All rights reserved.
      4  * Derived from dzkbd.c
      5  *
      6  * Copyright (c) 1992, 1993
      7  *	The Regents of the University of California.  All rights reserved.
      8  *
      9  * This software was developed by the Computer Systems Engineering group
     10  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
     11  * contributed to Berkeley.
     12  *
     13  * All advertising materials mentioning features or use of this software
     14  * must display the following acknowledgement:
     15  *	This product includes software developed by the University of
     16  *	California, Lawrence Berkeley Laboratory.
     17  *
     18  * Redistribution and use in source and binary forms, with or without
     19  * modification, are permitted provided that the following conditions
     20  * are met:
     21  * 1. Redistributions of source code must retain the above copyright
     22  *    notice, this list of conditions and the following disclaimer.
     23  * 2. Redistributions in binary form must reproduce the above copyright
     24  *    notice, this list of conditions and the following disclaimer in the
     25  *    documentation and/or other materials provided with the distribution.
     26  * 3. Neither the name of the University nor the names of its contributors
     27  *    may be used to endorse or promote products derived from this software
     28  *    without specific prior written permission.
     29  *
     30  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     31  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     32  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     33  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     34  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     35  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     36  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     37  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     38  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     39  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     40  * SUCH DAMAGE.
     41  *
     42  *	@(#)kbd.c	8.2 (Berkeley) 10/30/93
     43  */
     44 
     45 /*
     46  * LK200/LK400 keyboard attached to line 0 of the QVSS aux port
     47  */
     48 
     49 #include <sys/cdefs.h>
     50 __KERNEL_RCSID(0, "$$");
     51 
     52 #include <sys/param.h>
     53 #include <sys/systm.h>
     54 #include <sys/device.h>
     55 #include <sys/ioctl.h>
     56 #include <sys/syslog.h>
     57 #include <sys/malloc.h>
     58 #include <sys/intr.h>
     59 
     60 #include <dev/wscons/wsconsio.h>
     61 #include <dev/wscons/wskbdvar.h>
     62 #include <dev/wscons/wsksymdef.h>
     63 #include <dev/wscons/wsksymvar.h>
     64 #include <dev/dec/wskbdmap_lk201.h>
     65 
     66 #include <sys/bus.h>
     67 
     68 #include <vax/uba/qvareg.h>
     69 #include <vax/uba/qvavar.h>
     70 #include <vax/uba/qvkbdvar.h>
     71 #include <dev/dec/lk201reg.h>
     72 #include <dev/dec/lk201var.h>
     73 
     74 #include "locators.h"
     75 
     76 struct qvkbd_internal {
     77 	struct qvaux_linestate *qvi_ls;
     78 	struct lk201_state qvi_ks;
     79 };
     80 
     81 struct qvkbd_internal qvkbd_console_internal;
     82 
     83 struct qvkbd_softc {
     84 	struct device qvkbd_dev;	/* required first: base device */
     85 
     86 	struct qvkbd_internal *sc_itl;
     87 
     88 	int sc_enabled;
     89 	int kbd_type;
     90 
     91 	device_t sc_wskbddev;
     92 };
     93 
     94 static int	qvkbd_input(void *, int);
     95 
     96 static int	qvkbd_match(device_t, cfdata_t, void *);
     97 static void	qvkbd_attach(device_t, device_t, void *);
     98 
     99 CFATTACH_DECL_NEW(qvkbd, sizeof(struct qvkbd_softc),
    100     qvkbd_match, qvkbd_attach, NULL, NULL);
    101 
    102 static int	qvkbd_enable(void *, int);
    103 static void	qvkbd_set_leds(void *, int);
    104 static int	qvkbd_ioctl(void *, u_long, void *, int, struct lwp *);
    105 
    106 const struct wskbd_accessops qvkbd_accessops = {
    107 	qvkbd_enable,
    108 	qvkbd_set_leds,
    109 	qvkbd_ioctl,
    110 };
    111 
    112 static void	qvkbd_cngetc(void *, u_int *, int *);
    113 static void	qvkbd_cnpollc(void *, int);
    114 int             qvkbd_cnattach(struct qvaux_linestate *);
    115 
    116 const struct wskbd_consops qvkbd_consops = {
    117 	qvkbd_cngetc,
    118 	qvkbd_cnpollc,
    119 };
    120 
    121 static int qvkbd_sendchar(void *, u_char);
    122 
    123 const struct wskbd_mapdata qvkbd_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 qvaux line configured?
    134  */
    135 static int
    136 qvkbd_match(device_t parent, cfdata_t cf, void *aux)
    137 {
    138 	struct qvauxkm_attach_args *daa = aux;
    139 
    140 	/* Exact match is better than wildcard. */
    141 	if (cf->cf_loc[QVAUXCF_LINE] == daa->daa_line) {
    142 	        //printf("qvkbd_match: return 2\n");
    143 		return 2;
    144         }
    145 	/* This driver accepts wildcard. */
    146 	if (cf->cf_loc[QVAUXCF_LINE] == QVAUXCF_LINE_DEFAULT) {
    147 	        //printf("qvkbd_match: return 1\n");
    148  		return 1;
    149        }
    150         //printf("qvkbd_match: return 0\n");
    151 	return 0;
    152 }
    153 
    154 static void
    155 qvkbd_attach(device_t parent, device_t self, void *aux)
    156 {
    157 	struct qvaux_softc *qvaux = device_private(parent);
    158 	struct qvkbd_softc *qvkbd = device_private(self);
    159 	struct qvauxkm_attach_args *daa = aux;
    160 	struct qvaux_linestate *ls;
    161 	struct qvkbd_internal *qvi;
    162 	struct wskbddev_attach_args a;
    163 	int isconsole;
    164 
    165 	qvaux->sc_qvaux[daa->daa_line].qvaux_catch = qvkbd_input;
    166 	qvaux->sc_qvaux[daa->daa_line].qvaux_private = qvkbd;
    167 	ls = &qvaux->sc_qvaux[daa->daa_line];
    168 
    169 	isconsole = (daa->daa_flags & QVAUXKBD_CONSOLE);
    170 
    171 	if (isconsole) {
    172 		qvi = &qvkbd_console_internal;
    173 	} else {
    174 		qvi = malloc(sizeof(struct qvkbd_internal),
    175 				       M_DEVBUF, M_NOWAIT);
    176 		qvi->qvi_ks.attmt.sendchar = qvkbd_sendchar;
    177 		qvi->qvi_ks.attmt.cookie = ls;
    178 	}
    179 	qvi->qvi_ls = ls;
    180 	qvkbd->sc_itl = qvi;
    181 
    182 	printf("\n");
    183 
    184 	if (!isconsole) {
    185 		DELAY(100000);
    186 		lk201_init(&qvi->qvi_ks);
    187 	}
    188 
    189 	/* XXX should identify keyboard ID here XXX */
    190 	/* XXX layout and the number of LED is varying XXX */
    191         /* XXX ID done during kb init XXX */
    192 
    193 	// qvkbd->kbd_type = WSKBD_TYPE_LK201;
    194 
    195 	qvkbd->sc_enabled = 1;
    196 
    197 	a.console = isconsole;
    198 	a.keymap = &qvkbd_keymapdata;
    199 	a.accessops = &qvkbd_accessops;
    200 	a.accesscookie = qvkbd;
    201 
    202 	qvkbd->sc_wskbddev = config_found(self, &a, wskbddevprint);
    203 }
    204 
    205 int
    206 qvkbd_cnattach(struct qvaux_linestate *ls)
    207 {
    208 
    209 	qvkbd_console_internal.qvi_ks.attmt.sendchar = qvkbd_sendchar;
    210 	qvkbd_console_internal.qvi_ks.attmt.cookie = ls;
    211 	lk201_init(&qvkbd_console_internal.qvi_ks);
    212 	qvkbd_console_internal.qvi_ls = ls;
    213 
    214 	wskbd_cnattach(&qvkbd_consops, &qvkbd_console_internal,
    215 		       &qvkbd_keymapdata);
    216 
    217 	return 0;
    218 }
    219 
    220 static int
    221 qvkbd_enable(void *v, int on)
    222 {
    223 	struct qvkbd_softc *sc = v;
    224 
    225 	sc->sc_enabled = on;
    226 	return 0;
    227 }
    228 
    229 static int
    230 qvkbd_sendchar(void *v, u_char c)
    231 {
    232 	struct qvaux_linestate *ls = v;
    233 	int s;
    234 
    235 	s = spltty();
    236 	qvauxputc(ls, c);
    237 	splx(s);
    238 	return (0);
    239 }
    240 
    241 static void
    242 qvkbd_cngetc(void *v, u_int *type, int *data)
    243 {
    244 	struct qvkbd_internal *qvi = v;
    245 	int c;
    246 
    247 	do {
    248 		c = qvauxgetc(qvi->qvi_ls);
    249 	} while (!lk201_decode(&qvi->qvi_ks, 0, c, type, data));
    250 }
    251 
    252 static void
    253 qvkbd_cnpollc(void *v, int on)
    254 {
    255 #if 0
    256 	struct qvkbd_internal *qvi = v;
    257 #endif
    258 }
    259 
    260 static void
    261 qvkbd_set_leds(void *v, int leds)
    262 {
    263 	struct qvkbd_softc *sc = (struct qvkbd_softc *)v;
    264 
    265 	lk201_set_leds(&sc->sc_itl->qvi_ks, leds);
    266 }
    267 
    268 static int
    269 qvkbd_ioctl(void *v, u_long cmd, void *data, int flag, struct lwp *l)
    270 {
    271 	struct qvkbd_softc *sc = (struct qvkbd_softc *)v;
    272 
    273 	switch (cmd) {
    274 	case WSKBDIO_GTYPE:
    275 		*(int *)data = sc->kbd_type;
    276 		return 0;
    277 	case WSKBDIO_SETLEDS:
    278 		lk201_set_leds(&sc->sc_itl->qvi_ks, *(int *)data);
    279 		return 0;
    280 	case WSKBDIO_GETLEDS:
    281 		/* XXX don't dig in kbd internals */
    282 		*(int *)data = sc->sc_itl->qvi_ks.leds_state;
    283 		return 0;
    284 	case WSKBDIO_COMPLEXBELL:
    285 		lk201_bell(&sc->sc_itl->qvi_ks,
    286 			   (struct wskbd_bell_data *)data);
    287 		return 0;
    288 	case WSKBDIO_SETKEYCLICK:
    289 		lk201_set_keyclick(&sc->sc_itl->qvi_ks, *(int *)data);
    290 		return 0;
    291 	case WSKBDIO_GETKEYCLICK:
    292 		/* XXX don't dig in kbd internals */
    293 		*(int *)data = sc->sc_itl->qvi_ks.kcvol;
    294 		return 0;
    295 	}
    296 	return (EPASSTHROUGH);
    297 }
    298 
    299 static int
    300 qvkbd_input(void *v, int data)
    301 {
    302 	struct qvkbd_softc *sc = (struct qvkbd_softc *)v;
    303 	u_int type;
    304 	int val;
    305         int decode;
    306 
    307         do {
    308                 decode = lk201_decode(&sc->sc_itl->qvi_ks, 1,
    309                     data, &type, &val);
    310                 if (decode != LKD_NODATA)
    311                         wskbd_input(sc->sc_wskbddev, type, val);
    312         } while (decode == LKD_MORE);
    313 	return(1);
    314 }
    315 
    316