1 /* $OpenBSD: lunaws.c,v 1.11 2014/06/07 11:55:35 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 static const u_int8_t ch1_regs[6] = { 55 WR0_RSTINT, /* Reset E/S Interrupt */ 56 WR1_RXALLS, /* Rx per char, No Tx */ 57 0, /* */ 58 WR3_RX8BIT | WR3_RXENBL, /* Rx */ 59 WR4_BAUD96 | WR4_STOP1 | WR4_NPARITY, /* Tx/Rx */ 60 WR5_TX8BIT | WR5_TXENBL, /* Tx */ 61 }; 62 63 struct ws_softc { 64 struct device sc_dv; 65 struct sioreg *sc_ctl; 66 u_int8_t sc_wr[6]; 67 struct device *sc_wskbddev; 68 #if NWSMOUSE > 0 69 struct device *sc_wsmousedev; 70 int sc_msreport; 71 int buttons, dx, dy; 72 #endif 73 74 #ifdef WSDISPLAY_COMPAT_RAWKBD 75 int sc_rawkbd; 76 #endif 77 }; 78 79 void omkbd_input(void *, int); 80 void omkbd_decode(void *, int, u_int *, int *); 81 int omkbd_enable(void *, int); 82 void omkbd_set_leds(void *, int); 83 int omkbd_ioctl(void *, u_long, caddr_t, int, struct proc *); 84 85 const struct wskbd_mapdata omkbd_keymapdata = { 86 omkbd_keydesctab, 87 #ifdef OMKBD_LAYOUT 88 OMKBD_LAYOUT, 89 #else 90 KB_JP | KB_DEFAULT, 91 #endif 92 }; 93 94 const struct wskbd_accessops omkbd_accessops = { 95 omkbd_enable, 96 omkbd_set_leds, 97 omkbd_ioctl, 98 }; 99 100 void ws_cnattach(void); 101 void ws_cngetc(void *, u_int *, int *); 102 void ws_cnpollc(void *, int); 103 const struct wskbd_consops ws_consops = { 104 ws_cngetc, 105 ws_cnpollc, 106 NULL /* bell */ 107 }; 108 109 #if NWSMOUSE > 0 110 int omms_enable(void *); 111 int omms_ioctl(void *, u_long, caddr_t, int, struct proc *); 112 void omms_disable(void *); 113 114 const struct wsmouse_accessops omms_accessops = { 115 omms_enable, 116 omms_ioctl, 117 omms_disable, 118 }; 119 #endif 120 121 void wsintr(int); 122 123 int wsmatch(struct device *, void *, void *); 124 void wsattach(struct device *, struct device *, void *); 125 int ws_submatch_kbd(struct device *, void *, void *); 126 #if NWSMOUSE > 0 127 int ws_submatch_mouse(struct device *, void *, void *); 128 #endif 129 130 const struct cfattach ws_ca = { 131 sizeof(struct ws_softc), wsmatch, wsattach 132 }; 133 134 struct cfdriver ws_cd = { 135 NULL, "ws", DV_TTY 136 }; 137 138 extern int syscngetc(dev_t); 139 extern void syscnputc(dev_t, int); 140 141 int 142 wsmatch(struct device *parent, void *match, void *aux) 143 { 144 struct sio_attach_args *args = aux; 145 146 if (args->channel != 1) 147 return 0; 148 return 1; 149 } 150 151 void 152 wsattach(struct device *parent, struct device *self, void *aux) 153 { 154 struct ws_softc *sc = (struct ws_softc *)self; 155 struct sio_softc *scp = (struct sio_softc *)parent; 156 struct sio_attach_args *args = aux; 157 struct wskbddev_attach_args a; 158 159 sc->sc_ctl = (struct sioreg *)scp->scp_ctl + 1; 160 bcopy(ch1_regs, sc->sc_wr, sizeof(ch1_regs)); 161 scp->scp_intr[1] = wsintr; 162 163 setsioreg(sc->sc_ctl, WR0, sc->sc_wr[WR0]); 164 setsioreg(sc->sc_ctl, WR4, sc->sc_wr[WR4]); 165 setsioreg(sc->sc_ctl, WR3, sc->sc_wr[WR3]); 166 setsioreg(sc->sc_ctl, WR5, sc->sc_wr[WR5]); 167 setsioreg(sc->sc_ctl, WR0, sc->sc_wr[WR0]); 168 setsioreg(sc->sc_ctl, WR1, sc->sc_wr[WR1]); 169 170 syscnputc((dev_t)1, 0x20); /* keep quiet mouse */ 171 172 printf("\n"); 173 174 a.console = (args->hwflags == 1); 175 a.keymap = &omkbd_keymapdata; 176 a.accessops = &omkbd_accessops; 177 a.accesscookie = (void *)sc; 178 sc->sc_wskbddev = config_found_sm(self, &a, wskbddevprint, 179 ws_submatch_kbd); 180 181 #if NWSMOUSE > 0 182 { 183 struct wsmousedev_attach_args b; 184 b.accessops = &omms_accessops; 185 b.accesscookie = (void *)sc; 186 sc->sc_wsmousedev = config_found_sm(self, &b, wsmousedevprint, 187 ws_submatch_mouse); 188 sc->sc_msreport = 0; 189 } 190 #endif 191 } 192 193 int 194 ws_submatch_kbd(struct device *parent, void *match, void *aux) 195 { 196 struct cfdata *cf = match; 197 198 if (strcmp(cf->cf_driver->cd_name, "wskbd")) 199 return (0); 200 return ((*cf->cf_attach->ca_match)(parent, cf, aux)); 201 } 202 203 #if NWSMOUSE > 0 204 205 int 206 ws_submatch_mouse(struct device *parent, void *match, void *aux) 207 { 208 struct cfdata *cf = match; 209 210 if (strcmp(cf->cf_driver->cd_name, "wsmouse")) 211 return (0); 212 return ((*cf->cf_attach->ca_match)(parent, cf, aux)); 213 } 214 215 #endif 216 217 /*ARGSUSED*/ 218 void 219 wsintr(int chan) 220 { 221 struct ws_softc *sc = ws_cd.cd_devs[0]; 222 struct sioreg *sio = sc->sc_ctl; 223 u_int code; 224 int rr; 225 226 rr = getsiocsr(sio); 227 if (rr & RR_RXRDY) { 228 do { 229 code = sio->sio_data; 230 if (rr & (RR_FRAMING | RR_OVERRUN | RR_PARITY)) { 231 sio->sio_cmd = WR0_ERRRST; 232 continue; 233 } 234 #if NWSMOUSE > 0 235 /* 236 * if (code >= 0x80 && code <= 0x87), then 237 * it's the first byte of 3 byte long mouse report 238 * code[0] & 07 -> LMR button condition 239 * code[1], [2] -> x,y delta 240 * otherwise, key press or release event. 241 */ 242 if (sc->sc_msreport == 0) { 243 if (code < 0x80 || code > 0x87) { 244 omkbd_input(sc, code); 245 continue; 246 } 247 code = (code & 07) ^ 07; 248 /* LMR->RML: wsevent counts 0 for leftmost */ 249 sc->buttons = (code & 02); 250 if (code & 01) 251 sc->buttons |= 04; 252 if (code & 04) 253 sc->buttons |= 01; 254 sc->sc_msreport = 1; 255 } 256 else if (sc->sc_msreport == 1) { 257 sc->dx = (signed char)code; 258 sc->sc_msreport = 2; 259 } 260 else if (sc->sc_msreport == 2) { 261 sc->dy = (signed char)code; 262 if (sc->sc_wsmousedev != NULL) 263 wsmouse_input(sc->sc_wsmousedev, 264 sc->buttons, sc->dx, sc->dy, 0, 0, 265 WSMOUSE_INPUT_DELTA); 266 sc->sc_msreport = 0; 267 } 268 #else 269 omkbd_input(sc, code); 270 #endif 271 } while ((rr = getsiocsr(sio)) & RR_RXRDY); 272 } 273 if (rr & RR_TXRDY) 274 sio->sio_cmd = WR0_RSTPEND; 275 /* not capable of transmit, yet */ 276 } 277 278 void 279 omkbd_input(void *v, int data) 280 { 281 struct ws_softc *sc = v; 282 u_int type; 283 int key; 284 285 omkbd_decode(v, data, &type, &key); 286 287 #if WSDISPLAY_COMPAT_RAWKBD 288 if (sc->sc_rawkbd) { 289 u_char cbuf[2]; 290 int c, j = 0; 291 292 c = omkbd_raw[key]; 293 if (c != RAWKEY_Null) { 294 /* fake extended scancode if necessary */ 295 if (c & 0x80) 296 cbuf[j++] = 0xe0; 297 cbuf[j] = c & 0x7f; 298 if (type == WSCONS_EVENT_KEY_UP) 299 cbuf[j] |= 0x80; 300 j++; 301 302 wskbd_rawinput(sc->sc_wskbddev, cbuf, j); 303 } 304 } else 305 #endif 306 { 307 if (sc->sc_wskbddev != NULL) 308 wskbd_input(sc->sc_wskbddev, type, key); 309 } 310 } 311 312 void 313 omkbd_decode(void *v, int datain, u_int *type, int *dataout) 314 { 315 *type = (datain & 0x80) ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN; 316 *dataout = datain & 0x7f; 317 } 318 319 void 320 ws_cngetc(void *v, u_int *type, int *data) 321 { 322 int code; 323 324 code = syscngetc((dev_t)1); 325 omkbd_decode(v, code, type, data); 326 } 327 328 void 329 ws_cnpollc(void *v, int on) 330 { 331 } 332 333 /* EXPORT */ void 334 ws_cnattach() 335 { 336 static int voidfill; 337 338 /* XXX need CH.B initialization XXX */ 339 340 wskbd_cnattach(&ws_consops, &voidfill, &omkbd_keymapdata); 341 } 342 343 int 344 omkbd_enable(void *v, int on) 345 { 346 return 0; 347 } 348 349 void 350 omkbd_set_leds(void *v, int leds) 351 { 352 #if 0 353 syscnputc((dev_t)1, 0x10); /* kana LED on */ 354 syscnputc((dev_t)1, 0x00); /* kana LED off */ 355 syscnputc((dev_t)1, 0x11); /* caps LED on */ 356 syscnputc((dev_t)1, 0x01); /* caps LED off */ 357 #endif 358 } 359 360 int 361 omkbd_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p) 362 { 363 #if WSDISPLAY_COMPAT_RAWKBD 364 struct ws_softc *sc = v; 365 #endif 366 367 switch (cmd) { 368 case WSKBDIO_GTYPE: 369 *(int *)data = WSKBD_TYPE_LUNA; 370 return 0; 371 case WSKBDIO_SETLEDS: 372 case WSKBDIO_GETLEDS: 373 case WSKBDIO_COMPLEXBELL: /* XXX capable of complex bell */ 374 return -1; 375 #if WSDISPLAY_COMPAT_RAWKBD 376 case WSKBDIO_SETMODE: 377 sc->sc_rawkbd = *(int *)data == WSKBD_RAW; 378 return 0; 379 case WSKBDIO_GETMODE: 380 *(int *)data = sc->sc_rawkbd; 381 return 0; 382 #endif 383 } 384 return -1; 385 } 386 387 #if NWSMOUSE > 0 388 389 int 390 omms_enable(void *v) 391 { 392 struct ws_softc *sc = v; 393 394 syscnputc((dev_t)1, 0x60); /* enable 3 byte long mouse reporting */ 395 sc->sc_msreport = 0; 396 return 0; 397 } 398 399 /*ARGUSED*/ 400 int 401 omms_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p) 402 { 403 #if 0 404 struct ws_softc *sc = v; 405 #endif 406 407 switch (cmd) { 408 case WSMOUSEIO_GTYPE: 409 *(u_int *)data = WSMOUSE_TYPE_LUNA; 410 return 0; 411 } 412 413 return -1; 414 } 415 416 void 417 omms_disable(void *v) 418 { 419 struct ws_softc *sc = v; 420 421 syscnputc((dev_t)1, 0x20); /* quiet mouse */ 422 sc->sc_msreport = 0; 423 } 424 #endif 425