1 /* $NetBSD: lunaws.c,v 1.6 2002/03/17 19:40:42 atatat Exp $ */ 2 3 /*- 4 * Copyright (c) 2000 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Tohru Nishimura. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ 40 41 __KERNEL_RCSID(0, "$NetBSD: lunaws.c,v 1.6 2002/03/17 19:40:42 atatat Exp $"); 42 43 #include "wsmouse.h" 44 45 #include <sys/param.h> 46 #include <sys/systm.h> 47 #include <sys/conf.h> 48 #include <sys/device.h> 49 50 #include <dev/wscons/wsconsio.h> 51 #include <dev/wscons/wskbdvar.h> 52 #include <dev/wscons/wsksymdef.h> 53 #include <dev/wscons/wsksymvar.h> 54 #include <dev/wscons/wsmousevar.h> 55 56 #include <luna68k/dev/sioreg.h> 57 #include <luna68k/dev/siovar.h> 58 59 static const u_int8_t ch1_regs[6] = { 60 WR0_RSTINT, /* Reset E/S Interrupt */ 61 WR1_RXALLS, /* Rx per char, No Tx */ 62 0, /* */ 63 WR3_RX8BIT | WR3_RXENBL, /* Rx */ 64 WR4_BAUD96 | WR4_STOP1 | WR4_NPARITY, /* Tx/Rx */ 65 WR5_TX8BIT | WR5_TXENBL, /* Tx */ 66 }; 67 68 struct ws_softc { 69 struct device sc_dv; 70 struct sioreg *sc_ctl; 71 u_int8_t sc_wr[6]; 72 struct device *sc_wskbddev; 73 #if NWSMOUSE > 0 74 struct device *sc_wsmousedev; 75 int sc_msreport; 76 int buttons, dx, dy; 77 #endif 78 }; 79 80 static void omkbd_input __P((void *, int)); 81 static int omkbd_decode __P((void *, int, u_int *, int *)); 82 static int omkbd_enable __P((void *, int)); 83 static void omkbd_set_leds __P((void *, int)); 84 static int omkbd_ioctl __P((void *, u_long, caddr_t, int, struct proc *)); 85 86 struct wscons_keydesc omkbd_keydesctab[]; 87 88 static const struct wskbd_mapdata omkbd_keymapdata = { 89 omkbd_keydesctab, 90 KB_JP, 91 }; 92 static const struct wskbd_accessops omkbd_accessops = { 93 omkbd_enable, 94 omkbd_set_leds, 95 omkbd_ioctl, 96 }; 97 98 void ws_cnattach __P((void)); 99 static void ws_cngetc __P((void *, u_int *, int *)); 100 static void ws_cnpollc __P((void *, int)); 101 static const struct wskbd_consops ws_consops = { 102 ws_cngetc, 103 ws_cnpollc, 104 }; 105 106 #if NWSMOUSE > 0 107 static int omms_enable __P((void *)); 108 static int omms_ioctl __P((void *, u_long, caddr_t, int, struct proc *)); 109 static void omms_disable __P((void *)); 110 111 static const struct wsmouse_accessops omms_accessops = { 112 omms_enable, 113 omms_ioctl, 114 omms_disable, 115 }; 116 #endif 117 118 static void wsintr __P((int)); 119 120 static int wsmatch __P((struct device *, struct cfdata *, void *)); 121 static void wsattach __P((struct device *, struct device *, void *)); 122 static int ws_submatch_kbd __P((struct device *, struct cfdata *, void *)); 123 #if NWSMOUSE > 0 124 static int ws_submatch_mouse __P((struct device *, struct cfdata *, void *)); 125 #endif 126 127 const struct cfattach ws_ca = { 128 sizeof(struct ws_softc), wsmatch, wsattach 129 }; 130 extern struct cfdriver ws_cd; 131 132 extern int syscngetc __P((dev_t)); 133 extern void syscnputc __P((dev_t, int)); 134 135 static int 136 wsmatch(parent, match, aux) 137 struct device *parent; 138 struct cfdata *match; 139 void *aux; 140 { 141 struct sio_attach_args *args = aux; 142 143 if (args->channel != 1) 144 return 0; 145 return 1; 146 } 147 148 static void 149 wsattach(parent, self, aux) 150 struct device *parent; 151 struct device *self; 152 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 static int 194 ws_submatch_kbd(parent, cf, aux) 195 struct device *parent; 196 struct cfdata *cf; 197 void *aux; 198 { 199 200 if (strcmp(cf->cf_driver->cd_name, "wskbd")) 201 return (0); 202 return ((*cf->cf_attach->ca_match)(parent, cf, aux)); 203 } 204 205 #if NWSMOUSE > 0 206 207 static int 208 ws_submatch_mouse(parent, cf, aux) 209 struct device *parent; 210 struct cfdata *cf; 211 void *aux; 212 { 213 214 if (strcmp(cf->cf_driver->cd_name, "wsmouse")) 215 return (0); 216 return ((*cf->cf_attach->ca_match)(parent, cf, aux)); 217 } 218 219 #endif 220 221 /*ARGSUSED*/ 222 static void 223 wsintr(chan) 224 int chan; 225 { 226 struct ws_softc *sc = ws_cd.cd_devs[0]; 227 struct sioreg *sio = sc->sc_ctl; 228 u_int code; 229 int rr; 230 231 rr = getsiocsr(sio); 232 if (rr & RR_RXRDY) { 233 do { 234 code = sio->sio_data; 235 if (rr & (RR_FRAMING | RR_OVERRUN | RR_PARITY)) { 236 sio->sio_cmd = WR0_ERRRST; 237 continue; 238 } 239 #if NWSMOUSE > 0 240 /* 241 * if (code >= 0x80 && code <= 0x87), then 242 * it's the first byte of 3 byte long mouse report 243 * code[0] & 07 -> LMR button condition 244 * code[1], [2] -> x,y delta 245 * otherwise, key press or release event. 246 */ 247 if (sc->sc_msreport == 0) { 248 if (code < 0x80 || code > 0x87) { 249 omkbd_input(sc, code); 250 continue; 251 } 252 code = (code & 07) ^ 07; 253 /* LMR->RML: wsevent counts 0 for leftmost */ 254 sc->buttons = (code & 02); 255 if (code & 01) 256 sc->buttons |= 04; 257 if (code & 04) 258 sc->buttons |= 01; 259 sc->sc_msreport = 1; 260 } 261 else if (sc->sc_msreport == 1) { 262 sc->dx = (signed char)code; 263 sc->sc_msreport = 2; 264 } 265 else if (sc->sc_msreport == 2) { 266 sc->dy = (signed char)code; 267 wsmouse_input(sc->sc_wsmousedev, 268 sc->buttons, sc->dx, sc->dy, 0, 0); 269 sc->sc_msreport = 0; 270 } 271 #else 272 omkbd_input(sc, code); 273 #endif 274 } while ((rr = getsiocsr(sio)) & RR_RXRDY); 275 } 276 if (rr && RR_TXRDY) 277 sio->sio_cmd = WR0_RSTPEND; 278 /* not capable of transmit, yet */ 279 } 280 281 static void 282 omkbd_input(v, data) 283 void *v; 284 int data; 285 { 286 struct ws_softc *sc = v; 287 u_int type; 288 int key; 289 290 if (omkbd_decode(v, data, &type, &key)) 291 wskbd_input(sc->sc_wskbddev, type, key); 292 } 293 294 static int 295 omkbd_decode(v, datain, type, dataout) 296 void *v; 297 int datain; 298 u_int *type; 299 int *dataout; 300 { 301 *type = (datain & 0x80) ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN; 302 *dataout = datain & 0x7f; 303 return 1; 304 } 305 306 #define KC(n) KS_KEYCODE(n) 307 308 static const keysym_t omkbd_keydesc_1[] = { 309 /* pos command normal shifted */ 310 KC(0x9), KS_Tab, 311 KC(0xa), KS_Control_L, 312 KC(0xb), KS_Mode_switch, /* Kana */ 313 KC(0xc), KS_Shift_R, 314 KC(0xd), KS_Shift_L, 315 KC(0xe), KS_Caps_Lock, 316 KC(0xf), KS_Meta_L, /* Zenmen */ 317 KC(0x10), KS_Escape, 318 KC(0x11), KS_BackSpace, 319 KC(0x12), KS_Return, 320 KC(0x14), KS_space, 321 KC(0x15), KS_Delete, 322 KC(0x16), KS_Alt_L, /* Henkan */ 323 KC(0x17), KS_Alt_R, /* Kakutei */ 324 KC(0x18), KS_f11, /* Shokyo */ 325 KC(0x19), KS_f12, /* Yobidashi */ 326 KC(0x1a), KS_f13, /* Bunsetsu L */ 327 KC(0x1b), KS_f14, /* Bunsetsu R */ 328 KC(0x1c), KS_KP_Up, 329 KC(0x1d), KS_KP_Left, 330 KC(0x1e), KS_KP_Right, 331 KC(0x1f), KS_KP_Down, 332 /* KC(0x20), KS_f11, */ 333 /* KC(0x21), KS_f12, */ 334 KC(0x22), KS_1, KS_exclam, 335 KC(0x23), KS_2, KS_quotedbl, 336 KC(0x24), KS_3, KS_numbersign, 337 KC(0x25), KS_4, KS_dollar, 338 KC(0x26), KS_5, KS_percent, 339 KC(0x27), KS_6, KS_ampersand, 340 KC(0x28), KS_7, KS_apostrophe, 341 KC(0x29), KS_8, KS_parenleft, 342 KC(0x2a), KS_9, KS_parenright, 343 KC(0x2b), KS_0, 344 KC(0x2c), KS_minus, KS_equal, 345 KC(0x2d), KS_asciicircum, KS_asciitilde, 346 KC(0x2e), KS_backslash, KS_bar, 347 /* KC(0x30), KS_f13, */ 348 /* KC(0x31), KS_f14, */ 349 KC(0x32), KS_q, 350 KC(0x33), KS_w, 351 KC(0x34), KS_e, 352 KC(0x35), KS_r, 353 KC(0x36), KS_t, 354 KC(0x37), KS_y, 355 KC(0x38), KS_u, 356 KC(0x39), KS_i, 357 KC(0x3a), KS_o, 358 KC(0x3b), KS_p, 359 KC(0x3c), KS_at, KS_grave, 360 KC(0x3d), KS_bracketleft, KS_braceleft, 361 KC(0x42), KS_a, 362 KC(0x43), KS_s, 363 KC(0x44), KS_d, 364 KC(0x45), KS_f, 365 KC(0x46), KS_g, 366 KC(0x47), KS_h, 367 KC(0x48), KS_j, 368 KC(0x49), KS_k, 369 KC(0x4a), KS_l, 370 KC(0x4b), KS_semicolon, KS_plus, 371 KC(0x4c), KS_colon, KS_asterisk, 372 KC(0x4d), KS_bracketright, KS_braceright, 373 KC(0x52), KS_z, 374 KC(0x53), KS_x, 375 KC(0x54), KS_c, 376 KC(0x55), KS_v, 377 KC(0x56), KS_b, 378 KC(0x57), KS_n, 379 KC(0x58), KS_m, 380 KC(0x59), KS_comma, KS_less, 381 KC(0x5a), KS_period, KS_greater, 382 KC(0x5b), KS_slash, KS_question, 383 KC(0x5c), KS_underscore, 384 KC(0x60), KS_KP_Delete, 385 KC(0x61), KS_KP_Add, 386 KC(0x62), KS_KP_Subtract, 387 KC(0x63), KS_KP_7, 388 KC(0x64), KS_KP_8, 389 KC(0x65), KS_KP_9, 390 KC(0x66), KS_KP_4, 391 KC(0x67), KS_KP_5, 392 KC(0x68), KS_KP_6, 393 KC(0x69), KS_KP_1, 394 KC(0x6a), KS_KP_2, 395 KC(0x6b), KS_KP_3, 396 KC(0x6c), KS_KP_0, 397 KC(0x6d), KS_KP_Decimal, 398 KC(0x6e), KS_KP_Enter, 399 KC(0x72), KS_f1, 400 KC(0x73), KS_f2, 401 KC(0x74), KS_f3, 402 KC(0x75), KS_f4, 403 KC(0x76), KS_f5, 404 KC(0x77), KS_f6, 405 KC(0x78), KS_f7, 406 KC(0x79), KS_f8, 407 KC(0x7a), KS_f9, 408 KC(0x7b), KS_f10, 409 KC(0x7c), KS_KP_Multiply, 410 KC(0x7d), KS_KP_Divide, 411 KC(0x7e), KS_KP_Equal, 412 KC(0x7f), KS_KP_Separator, 413 }; 414 415 #define SIZE(map) (sizeof(map)/sizeof(keysym_t)) 416 417 struct wscons_keydesc omkbd_keydesctab[] = { 418 { KB_JP, 0, SIZE(omkbd_keydesc_1), omkbd_keydesc_1, }, 419 { 0, 0, 0, 0 }, 420 }; 421 422 static void 423 ws_cngetc(v, type, data) 424 void *v; 425 u_int *type; 426 int *data; 427 { 428 int code; 429 430 do { 431 code = syscngetc((dev_t)1); 432 } while (!omkbd_decode(v, code, type, data)); 433 } 434 435 static void 436 ws_cnpollc(v, on) 437 void *v; 438 int on; 439 { 440 } 441 442 /* EXPORT */ void 443 ws_cnattach() 444 { 445 static int voidfill; 446 447 /* XXX need CH.B initialization XXX */ 448 449 wskbd_cnattach(&ws_consops, &voidfill, &omkbd_keymapdata); 450 } 451 452 static int 453 omkbd_enable(v, on) 454 void *v; 455 int on; 456 { 457 return 0; 458 } 459 460 static void 461 omkbd_set_leds(v, leds) 462 void *v; 463 int leds; 464 { 465 #if 0 466 syscnputc((dev_t)1, 0x10); /* kana LED on */ 467 syscnputc((dev_t)1, 0x00); /* kana LED off */ 468 syscnputc((dev_t)1, 0x11); /* caps LED on */ 469 syscnputc((dev_t)1, 0x01); /* caps LED off */ 470 #endif 471 } 472 473 static int 474 omkbd_ioctl(v, cmd, data, flag, p) 475 void *v; 476 u_long cmd; 477 caddr_t data; 478 int flag; 479 struct proc *p; 480 { 481 switch (cmd) { 482 case WSKBDIO_GTYPE: 483 *(int *)data = 0x19991005 /* XXX */; 484 return 0; 485 case WSKBDIO_SETLEDS: 486 case WSKBDIO_GETLEDS: 487 case WSKBDIO_COMPLEXBELL: /* XXX capable of complex bell */ 488 return 0; 489 } 490 return EPASSTHROUGH; 491 } 492 493 #if NWSMOUSE > 0 494 495 static int 496 omms_enable(v) 497 void *v; 498 { 499 struct ws_softc *sc = v; 500 501 syscnputc((dev_t)1, 0x60); /* enable 3 byte long mouse reporting */ 502 sc->sc_msreport = 0; 503 return 0; 504 } 505 506 /*ARGUSED*/ 507 static int 508 omms_ioctl(v, cmd, data, flag, p) 509 void *v; 510 u_long cmd; 511 caddr_t data; 512 int flag; 513 struct proc *p; 514 { 515 if (cmd == WSMOUSEIO_GTYPE) { 516 *(u_int *)data = 0x19991005; /* XXX */ 517 return 0; 518 } 519 return EPASSTHROUGH; 520 } 521 522 static void 523 omms_disable(v) 524 void *v; 525 { 526 struct ws_softc *sc = v; 527 528 syscnputc((dev_t)1, 0x20); /* quiet mouse */ 529 sc->sc_msreport = 0; 530 } 531 #endif 532