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