xref: /openbsd/sys/arch/luna88k/dev/lunaws.c (revision 6f40fd34)
1 /*	$OpenBSD: lunaws.c,v 1.14 2017/06/10 12:23:00 aoyama Exp $	*/
2 /* $NetBSD: lunaws.c,v 1.6 2002/03/17 19:40:42 atatat Exp $ */
3 
4 /*-
5  * Copyright (c) 2000 The NetBSD Foundation, Inc.
6  * All rights reserved.
7  *
8  * This code is derived from software contributed to The NetBSD Foundation
9  * by Tohru Nishimura.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/conf.h>
36 #include <sys/device.h>
37 
38 #include <dev/wscons/wsconsio.h>
39 #include <dev/wscons/wskbdvar.h>
40 #include <dev/wscons/wsksymdef.h>
41 #include <dev/wscons/wsksymvar.h>
42 #ifdef WSDISPLAY_COMPAT_RAWKBD
43 #include <dev/wscons/wskbdraw.h>
44 #endif
45 #include "wsmouse.h"
46 #if NWSMOUSE > 0
47 #include <dev/wscons/wsmousevar.h>
48 #endif
49 
50 #include <luna88k/dev/omkbdmap.h>
51 #include <luna88k/dev/sioreg.h>
52 #include <luna88k/dev/siovar.h>
53 
54 #define OMKBD_RXQ_LEN		64
55 #define OMKBD_RXQ_LEN_MASK	(OMKBD_RXQ_LEN - 1)
56 #define OMKBD_NEXTRXQ(x)	(((x) + 1) & OMKBD_RXQ_LEN_MASK)
57 
58 static const u_int8_t ch1_regs[6] = {
59 	WR0_RSTINT,				/* Reset E/S Interrupt */
60 	WR1_RXALLS,				/* Rx per char, No Tx */
61 	0,					/* */
62 	WR3_RX8BIT | WR3_RXENBL,		/* Rx */
63 	WR4_BAUD96 | WR4_STOP1 | WR4_NPARITY,	/* Tx/Rx */
64 	WR5_TX8BIT | WR5_TXENBL,		/* Tx */
65 };
66 
67 struct ws_softc {
68 	struct device	sc_dev;
69 	struct sioreg	*sc_ctl;
70 	u_int8_t	sc_wr[6];
71 	struct device	*sc_wskbddev;
72 	u_int8_t	sc_rxq[OMKBD_RXQ_LEN];
73 	u_int		sc_rxqhead;
74 	u_int		sc_rxqtail;
75 #if NWSMOUSE > 0
76 	struct device	*sc_wsmousedev;
77 	int		sc_msreport;
78 	int		sc_msbuttons, sc_msdx, sc_msdy;
79 #endif
80 	void		*sc_si;
81 #ifdef WSDISPLAY_COMPAT_RAWKBD
82 	int		sc_rawkbd;
83 #endif
84 };
85 
86 void omkbd_input(void *, int);
87 void omkbd_decode(void *, int, u_int *, int *);
88 int  omkbd_enable(void *, int);
89 void omkbd_set_leds(void *, int);
90 int  omkbd_ioctl(void *, u_long, caddr_t, int, struct proc *);
91 
92 const struct wskbd_mapdata omkbd_keymapdata = {
93 	omkbd_keydesctab,
94 #ifdef	OMKBD_LAYOUT
95 	OMKBD_LAYOUT,
96 #else
97 	KB_JP | KB_DEFAULT,
98 #endif
99 };
100 
101 const struct wskbd_accessops omkbd_accessops = {
102 	omkbd_enable,
103 	omkbd_set_leds,
104 	omkbd_ioctl,
105 };
106 
107 void ws_cnattach(void);
108 void ws_cngetc(void *, u_int *, int *);
109 void ws_cnpollc(void *, int);
110 const struct wskbd_consops ws_consops = {
111 	ws_cngetc,
112 	ws_cnpollc,
113 	NULL	/* bell */
114 };
115 
116 #if NWSMOUSE > 0
117 int  omms_enable(void *);
118 int  omms_ioctl(void *, u_long, caddr_t, int, struct proc *);
119 void omms_disable(void *);
120 
121 const struct wsmouse_accessops omms_accessops = {
122 	omms_enable,
123 	omms_ioctl,
124 	omms_disable,
125 };
126 #endif
127 
128 void wsintr(void *);
129 void wssoftintr(void *);
130 
131 int  wsmatch(struct device *, void *, void *);
132 void wsattach(struct device *, struct device *, void *);
133 int  ws_submatch_kbd(struct device *, void *, void *);
134 #if NWSMOUSE > 0
135 int  ws_submatch_mouse(struct device *, void *, void *);
136 #endif
137 
138 const struct cfattach ws_ca = {
139 	sizeof(struct ws_softc), wsmatch, wsattach
140 };
141 
142 struct cfdriver ws_cd = {
143         NULL, "ws", DV_TTY
144 };
145 
146 extern int  syscngetc(dev_t);
147 extern void syscnputc(dev_t, int);
148 
149 int
150 wsmatch(struct device *parent, void *match, void *aux)
151 {
152 	struct sio_attach_args *args = aux;
153 
154 	if (args->channel != 1)
155 		return 0;
156 	return 1;
157 }
158 
159 void
160 wsattach(struct device *parent, struct device *self, void *aux)
161 {
162 	struct ws_softc *sc = (struct ws_softc *)self;
163 	struct sio_softc *siosc = (struct sio_softc *)parent;
164 	struct sio_attach_args *args = aux;
165 	int channel = args->channel;
166 	struct wskbddev_attach_args a;
167 
168 	sc->sc_ctl = &siosc->sc_ctl[channel];
169 	memcpy(sc->sc_wr, ch1_regs, sizeof(ch1_regs));
170 	siosc->sc_intrhand[channel].ih_func = wsintr;
171 	siosc->sc_intrhand[channel].ih_arg = sc;
172 
173 	setsioreg(sc->sc_ctl, WR0, sc->sc_wr[WR0]);
174 	setsioreg(sc->sc_ctl, WR4, sc->sc_wr[WR4]);
175 	setsioreg(sc->sc_ctl, WR3, sc->sc_wr[WR3]);
176 	setsioreg(sc->sc_ctl, WR5, sc->sc_wr[WR5]);
177 	setsioreg(sc->sc_ctl, WR0, sc->sc_wr[WR0]);
178 	setsioreg(sc->sc_ctl, WR1, sc->sc_wr[WR1]);
179 
180 	syscnputc((dev_t)1, 0x20); /* keep quiet mouse */
181 
182 	sc->sc_rxqhead = 0;
183 	sc->sc_rxqtail = 0;
184 
185 	sc->sc_si = softintr_establish(IPL_SOFTTTY, wssoftintr, sc);
186 
187 	printf("\n");
188 
189 	a.console = (args->hwflags == 1);
190 	a.keymap = &omkbd_keymapdata;
191 	a.accessops = &omkbd_accessops;
192 	a.accesscookie = (void *)sc;
193 	sc->sc_wskbddev = config_found_sm(self, &a, wskbddevprint,
194 					ws_submatch_kbd);
195 
196 #if NWSMOUSE > 0
197 	{
198 	struct wsmousedev_attach_args b;
199 	b.accessops = &omms_accessops;
200 	b.accesscookie = (void *)sc;
201 	sc->sc_wsmousedev = config_found_sm(self, &b, wsmousedevprint,
202 					ws_submatch_mouse);
203 	sc->sc_msreport = 0;
204 	}
205 #endif
206 }
207 
208 int
209 ws_submatch_kbd(struct device *parent, void *match, void *aux)
210 {
211 	struct cfdata *cf = match;
212 
213         if (strcmp(cf->cf_driver->cd_name, "wskbd"))
214                 return (0);
215         return ((*cf->cf_attach->ca_match)(parent, cf, aux));
216 }
217 
218 #if NWSMOUSE > 0
219 
220 int
221 ws_submatch_mouse(struct device *parent, void *match, void *aux)
222 {
223 	struct cfdata *cf = match;
224 
225         if (strcmp(cf->cf_driver->cd_name, "wsmouse"))
226                 return (0);
227         return ((*cf->cf_attach->ca_match)(parent, cf, aux));
228 }
229 
230 #endif
231 
232 /*ARGSUSED*/
233 void
234 wsintr(void *arg)
235 {
236 	struct ws_softc *sc = arg;
237 	struct sioreg *sio = sc->sc_ctl;
238 	u_int code;
239 	int rr;
240 
241 	rr = getsiocsr(sio);
242 	if (rr & RR_RXRDY) {
243 		do {
244 			code = sio->sio_data;
245 			if (rr & (RR_FRAMING | RR_OVERRUN | RR_PARITY)) {
246 				sio->sio_cmd = WR0_ERRRST;
247 				continue;
248 			}
249 			sc->sc_rxq[sc->sc_rxqtail] = code;
250 			sc->sc_rxqtail = OMKBD_NEXTRXQ(sc->sc_rxqtail);
251 		} while ((rr = getsiocsr(sio)) & RR_RXRDY);
252 		softintr_schedule(sc->sc_si);
253 	}
254 	if (rr & RR_TXRDY)
255 		sio->sio_cmd = WR0_RSTPEND;
256 	/* not capable of transmit, yet */
257 }
258 
259 void
260 wssoftintr(void *arg)
261 {
262 	struct ws_softc *sc = arg;
263 	uint8_t code;
264 
265 	while (sc->sc_rxqhead != sc->sc_rxqtail) {
266 		code = sc->sc_rxq[sc->sc_rxqhead];
267 		sc->sc_rxqhead = OMKBD_NEXTRXQ(sc->sc_rxqhead);
268 #if NWSMOUSE > 0
269 		/*
270 		 * if (code >= 0x80 && code <= 0x87), then
271 		 * it's the first byte of 3 byte long mouse report
272 		 * 	code[0] & 07 -> LMR button condition
273 		 * 	code[1], [2] -> x,y delta
274 		 * otherwise, key press or release event.
275 		 */
276 		if (sc->sc_msreport == 0) {
277 			if (code < 0x80 || code > 0x87) {
278 				omkbd_input(sc, code);
279 				continue;
280 			}
281 			code = (code & 07) ^ 07;
282 			/* LMR->RML: wsevent counts 0 for leftmost */
283 			sc->sc_msbuttons = (code & 02);
284 			if ((code & 01) != 0)
285 				sc->sc_msbuttons |= 04;
286 			if ((code & 04) != 0)
287 				sc->sc_msbuttons |= 01;
288 			sc->sc_msreport = 1;
289 		} else if (sc->sc_msreport == 1) {
290 			sc->sc_msdx = (int8_t)code;
291 			sc->sc_msreport = 2;
292 		} else if (sc->sc_msreport == 2) {
293 			sc->sc_msdy = (int8_t)code;
294 			WSMOUSE_INPUT(sc->sc_wsmousedev,
295 			    sc->sc_msbuttons, sc->sc_msdx, sc->sc_msdy, 0, 0);
296 			sc->sc_msreport = 0;
297 		}
298 #else
299 		omkbd_input(sc, code);
300 #endif
301 	}
302 }
303 
304 void
305 omkbd_input(void *v, int data)
306 {
307 	struct ws_softc *sc = v;
308 	u_int type;
309 	int key;
310 
311 	omkbd_decode(v, data, &type, &key);
312 
313 #if WSDISPLAY_COMPAT_RAWKBD
314 	if (sc->sc_rawkbd) {
315 		u_char cbuf[2];
316 		int c, j = 0;
317 
318 		c = omkbd_raw[key];
319 		if (c != RAWKEY_Null) {
320 			/* fake extended scancode if necessary */
321 			if (c & 0x80)
322 				cbuf[j++] = 0xe0;
323 			cbuf[j] = c & 0x7f;
324 			if (type == WSCONS_EVENT_KEY_UP)
325 				cbuf[j] |= 0x80;
326 			j++;
327 
328 			wskbd_rawinput(sc->sc_wskbddev, cbuf, j);
329 		}
330 	} else
331 #endif
332 	{
333 		if (sc->sc_wskbddev != NULL)
334 			wskbd_input(sc->sc_wskbddev, type, key);
335 	}
336 }
337 
338 void
339 omkbd_decode(void *v, int datain, u_int *type, int *dataout)
340 {
341 	*type = (datain & 0x80) ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN;
342 	*dataout = datain & 0x7f;
343 }
344 
345 void
346 ws_cngetc(void *v, u_int *type, int *data)
347 {
348 	int code;
349 
350 	code = syscngetc((dev_t)1);
351 	omkbd_decode(v, code, type, data);
352 }
353 
354 void
355 ws_cnpollc(void *v, int on)
356 {
357 }
358 
359 /* EXPORT */ void
360 ws_cnattach()
361 {
362 	static int voidfill;
363 
364 	/* XXX need CH.B initialization XXX */
365 
366 	wskbd_cnattach(&ws_consops, &voidfill, &omkbd_keymapdata);
367 }
368 
369 int
370 omkbd_enable(void *v, int on)
371 {
372 	return 0;
373 }
374 
375 void
376 omkbd_set_leds(void *v, int leds)
377 {
378 #if 0
379 	syscnputc((dev_t)1, 0x10); /* kana LED on */
380 	syscnputc((dev_t)1, 0x00); /* kana LED off */
381 	syscnputc((dev_t)1, 0x11); /* caps LED on */
382 	syscnputc((dev_t)1, 0x01); /* caps LED off */
383 #endif
384 }
385 
386 int
387 omkbd_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
388 {
389 #if WSDISPLAY_COMPAT_RAWKBD
390 	struct ws_softc *sc = v;
391 #endif
392 
393 	switch (cmd) {
394 	case WSKBDIO_GTYPE:
395 		*(int *)data = WSKBD_TYPE_LUNA;
396 		return 0;
397 	case WSKBDIO_SETLEDS:
398 	case WSKBDIO_GETLEDS:
399 	case WSKBDIO_COMPLEXBELL:	/* XXX capable of complex bell */
400 		return -1;
401 #if WSDISPLAY_COMPAT_RAWKBD
402 	case WSKBDIO_SETMODE:
403 		sc->sc_rawkbd = *(int *)data == WSKBD_RAW;
404 		return 0;
405 	case WSKBDIO_GETMODE:
406 		*(int *)data = sc->sc_rawkbd;
407 		return 0;
408 #endif
409 	}
410 	return -1;
411 }
412 
413 #if NWSMOUSE > 0
414 
415 int
416 omms_enable(void *v)
417 {
418 	struct ws_softc *sc = v;
419 
420 	syscnputc((dev_t)1, 0x60); /* enable 3 byte long mouse reporting */
421 	sc->sc_msreport = 0;
422 	return 0;
423 }
424 
425 /*ARGUSED*/
426 int
427 omms_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
428 {
429 
430 	switch (cmd) {
431 	case WSMOUSEIO_GTYPE:
432 		*(u_int *)data = WSMOUSE_TYPE_LUNA;
433 		return 0;
434 	}
435 
436 	return -1;
437 }
438 
439 void
440 omms_disable(void *v)
441 {
442 	struct ws_softc *sc = v;
443 
444 	syscnputc((dev_t)1, 0x20); /* quiet mouse */
445 	sc->sc_msreport = 0;
446 }
447 #endif
448