1 /* 2 * Copyright (c) 1992 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Sony Corp. and Kazumasa Utashiro of Software Research Associates, Inc. 7 * 8 * %sccs.include.redist.c% 9 * 10 * from: $Hdr: kb_ctrl.c,v 4.300 91/06/09 06:14:49 root Rel41 $ SONY 11 * 12 * @(#)kb_ctrl.c 7.1 (Berkeley) 06/04/92 13 */ 14 15 /* 16 * Keyboard driver 17 */ 18 19 #include "../include/fix_machine_type.h" 20 21 #ifdef IPC_MRX 22 #include "../../h/ioctl.h" 23 #include "../../iop/keyboard.h" 24 #include "../../iop/kbreg.h" 25 #else 26 #include "ioctl.h" 27 #include "param.h" 28 #include "systm.h" 29 #include "types.h" 30 #include "../iop/keyboard.h" 31 #include "../iop/kbreg.h" 32 #endif 33 34 extern int tmode; 35 extern int kbd_status; 36 37 int iscaps = 0; 38 int change_country = K_JAPANESE_J; 39 int country; 40 41 extern Key_table default_table[]; 42 43 #ifdef CPU_SINGLE 44 extern Key_table key_table[]; 45 Key_table *key_table_addr = key_table; 46 #endif 47 48 #ifdef CPU_DOUBLE 49 Key_table *key_table_addr = default_table; 50 #endif 51 52 #ifdef CPU_SINGLE 53 #include "ms.h" 54 #include "clist.h" 55 #include "ttydev.h" 56 #include "tty.h" 57 #include "../sio/scc.h" 58 #include "time.h" 59 #include "../iop/mouse.h" 60 61 extern int cnrint(); 62 63 kbd_open(chan) 64 int chan; 65 { 66 register int i; 67 68 #ifdef news700 69 scc_open(chan); 70 #endif 71 #if defined(news1700) || defined(news1200) || defined(news3400) 72 kbm_open(chan); 73 #endif 74 return (0); 75 } 76 77 kbd_read(chan, buf, n) 78 int chan; 79 char *buf; 80 int n; 81 { 82 #ifdef news700 83 register int i; 84 85 for (i = n; i > 0; i--) 86 *buf++ = scc_getc(chan); 87 return (n); 88 #endif 89 #if defined(news1700) || defined(news1200) 90 91 return (kbd_read_raw(chan, buf, n)); 92 #endif 93 } 94 95 kbd_write(chan, buf, n) 96 int chan; 97 char *buf; 98 int n; 99 { 100 #ifdef news700 101 register int i; 102 103 for (i = 0; i < n; i++) { 104 scc_putc(SCC_KEYBOARD, *buf++); 105 #ifndef NO_PRE_EMPT 106 if (i % 4 == 0) PRE_EMPT; 107 #endif 108 } 109 return (n); 110 #endif /* news700 */ 111 #if defined(news1700) || defined(news1200) || defined(news3400) 112 113 return (kbm_write(SCC_KEYBOARD, buf, n)); 114 #endif 115 } 116 117 kbd_back(buf, len) 118 register char *buf; 119 register int len; 120 { 121 int s; 122 123 while (--len >= 0) { 124 s = spltty(); 125 cnrint(*buf++); 126 (void) splx(s); 127 } 128 return (0); 129 } 130 131 #define KBPRI (PZERO+1) 132 133 struct clist scode_buf; 134 struct clist keyboard_buf; 135 char kb_rwait; 136 137 kbd_flush() 138 { 139 140 ndflush(&scode_buf, scode_buf.c_cc); 141 return (0); 142 } 143 144 static 145 kbd_put_raw(scode) 146 int scode; 147 { 148 extern char kb_busy; 149 150 if (kb_busy) { 151 if (scode_buf.c_cc < CBSIZE) 152 putc(scode, &scode_buf); 153 if (kb_rwait) { 154 kb_rwait = 0; 155 wakeup((caddr_t)&kb_rwait); 156 } 157 } 158 return (scode); 159 160 } 161 162 kbd_read_raw(chan, buf, count) 163 int chan; 164 char *buf; 165 register int count; 166 { 167 register int i; 168 register int n; 169 register int s; 170 171 if (count <= 0) 172 return (count); 173 s = splscc(); 174 while ((n = min(scode_buf.c_cc, count)) == 0) { 175 kb_rwait = 1; 176 sleep((caddr_t)&kb_rwait, KBPRI); 177 kb_rwait = 0; 178 } 179 (void) splx(s); 180 for (i = n; i > 0 ; i--) 181 *buf++ = getc(&scode_buf); 182 return (n); 183 } 184 185 kbd_nread() 186 { 187 188 return (scode_buf.c_cc); 189 } 190 191 kbd_bell(n) 192 register int n; 193 { 194 195 #if defined(news1700) || defined(news1200) || defined(news3400) 196 (void) kbm_write(SCC_KEYBOARD, NULL, n); 197 #endif 198 #ifdef news700 199 kbd_bell_scc(n); 200 #endif 201 return (0); 202 } 203 204 kbd_putcode(code) 205 int code; 206 { 207 int c; 208 209 kbd_put_raw(code); 210 kbd_encode(code); 211 while ((c = getc(&keyboard_buf)) != -1) 212 cnrint(c); 213 } 214 215 put_code(buf, cnt) 216 register char *buf; 217 register int cnt; 218 { 219 220 while (--cnt >= 0) 221 putc(*buf++, &keyboard_buf); 222 } 223 224 kb_softint() 225 { 226 int code; 227 extern int tty00_is_console; 228 229 while ((code = xgetc(SCC_KEYBOARD)) >= 0) { 230 #if defined(news1200) || defined(news3200) /* BEGIN reiko */ 231 if ((code & 0x7f) == KEY_EISUU) { 232 int up = code & OFF; 233 static int kana = 0; 234 235 if (kana) { 236 if (up) { 237 kana = 0; 238 } 239 } else { 240 if (up) { 241 code = KEY_KANA | OFF; 242 kana = 1; 243 } else { 244 code = KEY_KANA; 245 } 246 } 247 } 248 #endif 249 250 #ifdef NOTDEF /* KU:XXX */ 251 if (!tty00_is_console) 252 #endif 253 rst_dimmer_cnt(); 254 #if NMS > 0 255 if (!mskeytrigger(0, code & OFF, code & 0x7f)) 256 #endif 257 kbd_putcode(code); 258 } 259 } 260 #endif /* CPU_SINGLE */ 261 262 #ifdef IPC_MRX 263 #include "mrx.h" 264 #include "queue.h" 265 #include "process.h" 266 #include "buffer.h" 267 #include "port.h" 268 #include "message.h" 269 #include "machdep.h" 270 #include "malloc.h" 271 #include "config.h" 272 #include "kbms.h" 273 274 #ifdef news1800 275 #include "scc.h" 276 #endif 277 278 static struct buffer *kbd_buf; 279 static int port_kbd_intr; 280 static int port_kbd_back; 281 static int port_kbd_ctrl; 282 283 keyboard(chan) 284 int chan; 285 { 286 int kbd_ctrl(), kbd_output(); 287 int kbd_read(), kbd_ioctl(), kbd_io(); 288 289 #ifdef news3800 290 extern int (*Xkb_intr)(); 291 int kb_intr(); 292 293 Xkb_intr = kb_intr; 294 #endif 295 296 #ifdef news1800 297 int scc_input(), scc_output(); 298 299 if (scc_open(SCC_KEYBOARD) < 0) 300 return; 301 proc_create("scc_kbread", scc_input, 601, 512, SCC_KEYBOARD); 302 proc_create("scc_kbwrite", scc_output, 601, 512, SCC_KEYBOARD); 303 while (scc_std_ports[SCC_KEYBOARD][0] == 0) 304 proc_sleep_self(100); 305 #endif 306 kb_ioctl = kbd_ioctl; 307 kb_read = kbd_read; 308 kbd_init(); 309 proc_create("kbd_ctrl", kbd_ctrl, 300, DEFAULT_STACK_SIZE, 0); 310 proc_create("kbd_output", kbd_output, 300, DEFAULT_STACK_SIZE, 0); 311 proc_create("kbd_io", kbd_io, 300, DEFAULT_STACK_SIZE, 0); 312 } 313 314 int (*reset_dimmer)(); 315 316 kbd_ctrl() 317 { 318 register int m, n; 319 register int select; 320 int *len, from, count; 321 char *addr; 322 int ports[3]; 323 static char buf[16]; 324 325 ports[0] = port_kbd_intr = port_create("kb_intr"); 326 ports[1] = port_kbd_back = port_create("kb_echoback"); 327 ports[2] = port_kbd_ctrl = STDPORT; 328 329 #ifdef news3800 330 *(char *)KEYBD_RESET = 0; 331 *(char *)KEYBD_INTE = 1; 332 #endif 333 #ifdef news1800 334 count = 1; 335 msg_send(scc_std_ports[SCC_KEYBOARD][0], ports[0], 336 &count, sizeof (count), 0); 337 #endif 338 339 kbd_buf = buffer_alloc(32); 340 (void) spl0(); 341 for (;;) { 342 if (buffer_status(kbd_buf) > 0) 343 m = 3; 344 else 345 m = 2; 346 if ((select = msg_select(m, ports)) == 0) { 347 msg_recv(ports[0], NULL, &addr, &count, 0); 348 if (reset_dimmer) 349 (*reset_dimmer)(); 350 while (--count >= 0) { 351 if (send_mouse == 0 || (*send_mouse)(*addr) == 0) 352 kbd_encode(*addr); 353 addr++; 354 } 355 #ifdef news1800 356 count = 1; 357 msg_send(scc_std_ports[SCC_KEYBOARD][0], ports[select], 358 &count, sizeof (count), 0); 359 #endif 360 } else if (select == 1) { /* ESC [ 6 n */ 361 msg_recv(ports[select], NULL, &addr, &count, 0); 362 put(kbd_buf, addr, count); 363 } else { 364 msg_recv(ports[select], &from, &len, NULL, 0); 365 n = buffer_status(kbd_buf); 366 n = min(n, *len); 367 n = get(kbd_buf, buf, min(n, sizeof (buf))); 368 msg_send(from, ports[select], buf, n, 0); 369 } 370 } 371 } 372 373 kbd_output() 374 { 375 char *addr; 376 int from, len; 377 #ifdef news1800 378 register int subport; 379 380 subport = port_create("port_kbd_write"); 381 #endif 382 383 (void) spl0(); 384 for (;;) { 385 msg_recv(STDPORT, &from, &addr, &len, 0); 386 #ifdef news3800 387 len = kbd_write(0, addr, len); 388 #endif 389 #ifdef news1800 390 len = kbd_write(subport, addr, len); 391 #endif 392 msg_send(from, STDPORT, &len, sizeof(len), 0); 393 } 394 } 395 396 kbd_io() 397 { 398 struct kb_ctrl_req *req; 399 int from, reply; 400 #ifdef news1800 401 register int sub_port; 402 403 sub_port = port_create("port_kbd_sub"); 404 #endif 405 406 (void) spl0(); 407 for (;;) { 408 msg_recv(STDPORT, &from, &req, NULL, 0); 409 if (req->kb_func == KIOCCHTBL || req->kb_func == KIOCOYATBL) 410 kbd_ioctl(0, req->kb_func, req->kb_arg); 411 else 412 #ifdef news1800 413 kbd_ioctl(sub_port, req->kb_func, &req->kb_arg); 414 #else 415 kbd_ioctl(0, req->kb_func, &req->kb_arg); 416 #endif 417 reply = req->kb_arg; 418 msg_send(from, STDPORT, &reply, sizeof(reply), 0); 419 } 420 } 421 422 kbd_read(chan, buf, n) 423 int chan; 424 char *buf; 425 int n; 426 { 427 static int port; 428 char *addr; 429 int len; 430 431 if (port == 0) 432 port = port_create("port_kbd_read"); 433 if (n <= 0) 434 return (0); 435 msg_send(port_kbd_ctrl, port, &n, sizeof (n), 0); 436 msg_recv(port, NULL, &addr, &len, 0); 437 bcopy(addr, buf, len); 438 msg_free(port); 439 return (len); 440 } 441 442 kbd_write(chan, buf, n) 443 int chan; 444 char *buf; 445 int n; 446 { 447 #ifdef news1800 448 return (scc_write(chan, SCC_KEYBOARD, buf, n)); 449 #endif 450 451 #ifdef news3800 452 *(char *)BEEP_FREQ = ~(n & 1); 453 *(char *)KEYBD_BEEP = 1; 454 return (n); 455 #endif 456 } 457 458 kbd_back(buf, len) 459 char *buf; 460 int len; 461 { 462 463 msg_send(port_kbd_back, 0, buf, len, 0); 464 return (0); 465 } 466 467 kbd_nread() 468 { 469 470 return (buffer_status(kbd_buf)); 471 } 472 473 kbd_flush() 474 { 475 476 buffer_flush(kbd_buf); 477 return (0); 478 } 479 480 #ifdef news3800 481 kb_intr() 482 { 483 char c; 484 485 if (port_kbd_intr > 0) 486 while (*(char *)KBMS_STAT & (1 << b_KBREADY)) { 487 c = *(char *)KEYBD_DATA; 488 msg_send(port_kbd_intr, 0, &c, sizeof (char), 0); 489 } 490 } 491 #endif /* news3800 */ 492 493 kbd_bell(n, port) 494 int n, port; 495 { 496 497 #ifdef news3800 498 (void) kbd_write(0, NULL, n); 499 #else 500 kbd_bell_scc(n, port); 501 #endif 502 return (0); 503 } 504 505 put_code(buf, cnt) 506 char *buf; 507 int cnt; 508 { 509 510 put(kbd_buf, buf, cnt); 511 } 512 #endif /* IPC_MRX */ 513 514 kbd_ioctl(chan, cmd, argp) 515 int chan; 516 int cmd; 517 int *argp; 518 { 519 switch (cmd) { 520 521 case KIOCFLUSH: 522 return (kbd_flush()); 523 524 case KIOCSETS: 525 case KIOCGETS: 526 return (kbd_string(cmd, (Pfk_string *)argp)); 527 528 case KIOCBELL: 529 #ifdef news1800 530 return (kbd_bell(*argp, chan)); 531 #else 532 return (kbd_bell(*argp)); 533 #endif 534 535 case KIOCBACK: 536 if (argp == NULL) 537 return (-1); 538 if ((int)((Key_string *)argp)->key_string == NULL) 539 return (-1); 540 if ((int)((Key_string *)argp)->key_length <= 0) 541 return (-1); 542 return (kbd_back(((Key_string *)argp)->key_string, 543 ((Key_string *)argp)->key_length)); 544 545 case KIOCREPT: 546 return (kbd_repeat(1)); 547 548 case KIOCNRPT: 549 return (kbd_repeat(0)); 550 551 case KIOCNREAD: 552 *argp = kbd_nread(); 553 return (0); 554 555 case KIOCSETLOCK: 556 iscaps = *argp; 557 return (0); 558 559 case KIOCGETCNUM: 560 *argp = country; 561 return (0); 562 563 case KIOCSETCNUM: 564 country = *argp; 565 change_country = country; 566 return (0); 567 568 case KIOCDEFTBL: 569 key_table_addr = default_table; 570 country = K_JAPANESE_J; 571 return (0); 572 573 case KIOCCHTBL: 574 key_table_addr = (Key_table *)argp; 575 country = change_country; 576 return (0); 577 578 case KIOCGETSTAT: 579 *argp = kbd_status; 580 return (0); 581 582 case KIOCSETSTAT: 583 kbd_status = *argp; 584 return (0); 585 586 default: 587 return (-1); 588 } 589 } 590 591 #ifdef news1800 592 kbd_bell_scc(n, port) 593 register int n, port; 594 #else 595 kbd_bell_scc(n) 596 register int n; 597 #endif 598 { 599 register int i; 600 static char bell_data[] = { 601 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 602 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 603 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 604 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0 605 }; 606 607 while (n > 0) { 608 i = min(n, sizeof (bell_data)); 609 #ifdef news1800 610 (void) kbd_write(port, bell_data, i); 611 #else 612 (void) kbd_write(0, bell_data, i); 613 #endif 614 n -= i; 615 } 616 } 617 618 #ifdef KBDEBUG 619 scc_error_puts(chan, buf) 620 int chan; 621 char *buf; 622 { 623 while (*buf) { 624 scc_error_write(chan, *buf++, 1); 625 } 626 } 627 628 scc_error_write_hex(chan, n, zs) 629 int chan; 630 unsigned int n; 631 int zs; 632 { 633 int i; 634 int tmp, al; 635 static char hex[] = "0123456789abcdef"; 636 637 al = 0; 638 639 for (i = 28; i >= 0; i -= 4) { 640 tmp = (n >> i) & 0x0f; 641 if (tmp || al || !zs || !i) { 642 al++; 643 scc_error_write(chan, hex[tmp], 1); 644 } 645 } 646 } 647 #endif /* KBDEBUG */ 648