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