xref: /original-bsd/sys/news3400/bm/kb_ctrl.c (revision 3705696b)
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 
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 
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 
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 
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 
114 kbd_flush()
115 {
116 
117 	ndflush(&scode_buf, scode_buf.c_cc);
118 	return (0);
119 }
120 
121 static
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 
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 
162 kbd_nread()
163 {
164 
165 	return (scode_buf.c_cc);
166 }
167 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
396 kbd_nread()
397 {
398 
399 	return (buffer_status(kbd_buf));
400 }
401 
402 kbd_flush()
403 {
404 
405 	buffer_flush(kbd_buf);
406 	return (0);
407 }
408 
409 #ifdef news3800
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 
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 
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 
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 
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
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 
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