Commit | Line | Data |
---|---|---|
af5295ff KM |
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) %G% | |
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 */ |