xref: /openbsd/sys/arch/luna88k/dev/lunaws.c (revision 5b133f3f)
1 /*	$OpenBSD: lunaws.c,v 1.16 2023/03/08 04:43:07 guenther 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
wsmatch(struct device * parent,void * match,void * aux)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
wsattach(struct device * parent,struct device * self,void * aux)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
ws_submatch_kbd(struct device * parent,void * match,void * aux)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
ws_submatch_mouse(struct device * parent,void * match,void * aux)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 void
wsintr(void * arg)233 wsintr(void *arg)
234 {
235 	struct ws_softc *sc = arg;
236 	struct sioreg *sio = sc->sc_ctl;
237 	u_int code;
238 	int rr;
239 
240 	rr = getsiocsr(sio);
241 	if (rr & RR_RXRDY) {
242 		do {
243 			code = sio->sio_data;
244 			if (rr & (RR_FRAMING | RR_OVERRUN | RR_PARITY)) {
245 				sio->sio_cmd = WR0_ERRRST;
246 				continue;
247 			}
248 			sc->sc_rxq[sc->sc_rxqtail] = code;
249 			sc->sc_rxqtail = OMKBD_NEXTRXQ(sc->sc_rxqtail);
250 		} while ((rr = getsiocsr(sio)) & RR_RXRDY);
251 		softintr_schedule(sc->sc_si);
252 	}
253 	if (rr & RR_TXRDY)
254 		sio->sio_cmd = WR0_RSTPEND;
255 	/* not capable of transmit, yet */
256 }
257 
258 void
wssoftintr(void * arg)259 wssoftintr(void *arg)
260 {
261 	struct ws_softc *sc = arg;
262 	uint8_t code;
263 
264 	while (sc->sc_rxqhead != sc->sc_rxqtail) {
265 		code = sc->sc_rxq[sc->sc_rxqhead];
266 		sc->sc_rxqhead = OMKBD_NEXTRXQ(sc->sc_rxqhead);
267 #if NWSMOUSE > 0
268 		/*
269 		 * if (code >= 0x80 && code <= 0x87), then
270 		 * it's the first byte of 3 byte long mouse report
271 		 * 	code[0] & 07 -> LMR button condition
272 		 * 	code[1], [2] -> x,y delta
273 		 * otherwise, key press or release event.
274 		 */
275 		if (sc->sc_msreport == 0) {
276 			if (code < 0x80 || code > 0x87) {
277 				omkbd_input(sc, code);
278 				continue;
279 			}
280 			code = (code & 07) ^ 07;
281 			/* LMR->RML: wsevent counts 0 for leftmost */
282 			sc->sc_msbuttons = (code & 02);
283 			if ((code & 01) != 0)
284 				sc->sc_msbuttons |= 04;
285 			if ((code & 04) != 0)
286 				sc->sc_msbuttons |= 01;
287 			sc->sc_msreport = 1;
288 		} else if (sc->sc_msreport == 1) {
289 			sc->sc_msdx = (int8_t)code;
290 			sc->sc_msreport = 2;
291 		} else if (sc->sc_msreport == 2) {
292 			sc->sc_msdy = (int8_t)code;
293 			WSMOUSE_INPUT(sc->sc_wsmousedev,
294 			    sc->sc_msbuttons, sc->sc_msdx, sc->sc_msdy, 0, 0);
295 			sc->sc_msreport = 0;
296 		}
297 #else
298 		omkbd_input(sc, code);
299 #endif
300 	}
301 }
302 
303 void
omkbd_input(void * v,int data)304 omkbd_input(void *v, int data)
305 {
306 	struct ws_softc *sc = v;
307 	u_int type;
308 	int key;
309 
310 	omkbd_decode(v, data, &type, &key);
311 
312 #if WSDISPLAY_COMPAT_RAWKBD
313 	if (sc->sc_rawkbd) {
314 		u_char cbuf[2];
315 		int c, j = 0;
316 
317 		c = omkbd_raw[key];
318 		if (c != RAWKEY_Null) {
319 			/* fake extended scancode if necessary */
320 			if (c & 0x80)
321 				cbuf[j++] = 0xe0;
322 			cbuf[j] = c & 0x7f;
323 			if (type == WSCONS_EVENT_KEY_UP)
324 				cbuf[j] |= 0x80;
325 			j++;
326 
327 			wskbd_rawinput(sc->sc_wskbddev, cbuf, j);
328 		}
329 	} else
330 #endif
331 	{
332 		if (sc->sc_wskbddev != NULL)
333 			wskbd_input(sc->sc_wskbddev, type, key);
334 	}
335 }
336 
337 void
omkbd_decode(void * v,int datain,u_int * type,int * dataout)338 omkbd_decode(void *v, int datain, u_int *type, int *dataout)
339 {
340 	*type = (datain & 0x80) ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN;
341 	*dataout = datain & 0x7f;
342 }
343 
344 void
ws_cngetc(void * v,u_int * type,int * data)345 ws_cngetc(void *v, u_int *type, int *data)
346 {
347 	int code;
348 
349 	code = syscngetc((dev_t)1);
350 	omkbd_decode(v, code, type, data);
351 }
352 
353 void
ws_cnpollc(void * v,int on)354 ws_cnpollc(void *v, int on)
355 {
356 }
357 
358 /* EXPORT */ void
ws_cnattach()359 ws_cnattach()
360 {
361 	static int voidfill;
362 
363 	/* XXX need CH.B initialization XXX */
364 
365 	wskbd_cnattach(&ws_consops, &voidfill, &omkbd_keymapdata);
366 }
367 
368 int
omkbd_enable(void * v,int on)369 omkbd_enable(void *v, int on)
370 {
371 	return 0;
372 }
373 
374 void
omkbd_set_leds(void * v,int leds)375 omkbd_set_leds(void *v, int leds)
376 {
377 #if 0
378 	syscnputc((dev_t)1, 0x10); /* kana LED on */
379 	syscnputc((dev_t)1, 0x00); /* kana LED off */
380 	syscnputc((dev_t)1, 0x11); /* caps LED on */
381 	syscnputc((dev_t)1, 0x01); /* caps LED off */
382 #endif
383 }
384 
385 int
omkbd_ioctl(void * v,u_long cmd,caddr_t data,int flag,struct proc * p)386 omkbd_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
387 {
388 #if WSDISPLAY_COMPAT_RAWKBD
389 	struct ws_softc *sc = v;
390 #endif
391 
392 	switch (cmd) {
393 	case WSKBDIO_GTYPE:
394 		*(int *)data = WSKBD_TYPE_LUNA;
395 		return 0;
396 	case WSKBDIO_SETLEDS:
397 	case WSKBDIO_GETLEDS:
398 	case WSKBDIO_COMPLEXBELL:	/* XXX capable of complex bell */
399 		return -1;
400 #if WSDISPLAY_COMPAT_RAWKBD
401 	case WSKBDIO_SETMODE:
402 		sc->sc_rawkbd = *(int *)data == WSKBD_RAW;
403 		return 0;
404 	case WSKBDIO_GETMODE:
405 		*(int *)data = sc->sc_rawkbd;
406 		return 0;
407 #endif
408 	}
409 	return -1;
410 }
411 
412 #if NWSMOUSE > 0
413 
414 int
omms_enable(void * v)415 omms_enable(void *v)
416 {
417 	struct ws_softc *sc = v;
418 
419 	syscnputc((dev_t)1, 0x60); /* enable 3 byte long mouse reporting */
420 	sc->sc_msreport = 0;
421 	return 0;
422 }
423 
424 /*ARGUSED*/
425 int
omms_ioctl(void * v,u_long cmd,caddr_t data,int flag,struct proc * p)426 omms_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
427 {
428 
429 	switch (cmd) {
430 	case WSMOUSEIO_GTYPE:
431 		*(u_int *)data = WSMOUSE_TYPE_LUNA;
432 		return 0;
433 	}
434 
435 	return -1;
436 }
437 
438 void
omms_disable(void * v)439 omms_disable(void *v)
440 {
441 	struct ws_softc *sc = v;
442 
443 	syscnputc((dev_t)1, 0x20); /* quiet mouse */
444 	sc->sc_msreport = 0;
445 }
446 #endif
447