xref: /original-bsd/sys/news3400/bm/kb_ctrl.c (revision 135ce860)
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