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