xref: /original-bsd/sys/news3400/bm/bmcons.c (revision 36940495)
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: cons.c,v 4.300 91/06/09 06:34:41 root Rel41 $ SONY
11  *
12  *	@(#)bmcons.c	8.1 (Berkeley) 06/10/93
13  */
14 
15 /*
16  * console driver
17  */
18 #include <sys/param.h>
19 #include <machine/pte.h>
20 #include <sys/conf.h>
21 #include <sys/proc.h>
22 #include <sys/user.h>
23 #include <sys/ioctl.h>
24 #include <sys/tty.h>
25 #include <sys/map.h>
26 #include <sys/buf.h>
27 #include <sys/clist.h>
28 #include <sys/file.h>
29 #include "bm.h"
30 
31 #include <news3400/hbdev/rsreg.h>
32 #include <news3400/sio/sccparam.h>
33 
34 #define	CN_RXE		RXE
35 #define	CN_TXE		TXE
36 #define	CN_ON		(RXE|TXE|RTS|DTR)
37 #define	CN_OFF		0
38 #define	CN_RTS		RTS
39 #define	CN_DTR		DTR
40 #define	CN_CTS		CTS
41 #define	CN_DCD		DCD
42 #define	CN_DSR		DSR
43 #define	CN_RI		RI
44 #define	CN_BRK		XBREAK
45 
46 /*
47  * Local variables for the driver
48  */
49 
50 #define	splcons	spltty
51 
52 char cn_active[1];
53 char cn_stopped[1];
54 struct tty cn_tty[1];
55 
56 void	cnstart();
57 int	ttrstrt();
58 int	cnrint(), cnxint(), cnsint();
59 
60 bmattach(i)
61 {
62 	        /* temporary hack for pseudo-device initialization */;
63 }
64 
65 /*
66  * Open console. Turn on console if this is the first use of it.
67  */
68 /*ARGSUSED*/
69 cnopen(dev, flag, mode, p)
70 	dev_t dev;
71 	int flag, mode;
72 	struct proc *p;
73 {
74 	register struct tty *tp = &cn_tty[0];
75 
76 	if (cn_active[0] == 0) {
77 		if (cn_init() < 0)
78 			return (ENXIO);
79 		cn_enable();
80 		cn_active[0] = 1;
81 	}
82 	if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0)
83 		return (EBUSY);
84 	tp->t_addr = (caddr_t)0;
85 	tp->t_oproc = cnstart;
86 	tp->t_state |= TS_WOPEN;
87 	/*
88 	 * If this is first open, initialze tty state to default.
89 	 */
90 	if ((tp->t_state & TS_ISOPEN) == 0) {
91 		tp->t_state |= TS_WOPEN;
92 		ttychars(tp);
93 		if (tp->t_ispeed == 0) {
94 			tp->t_iflag = TTYDEF_IFLAG;
95 			tp->t_oflag = TTYDEF_OFLAG;
96 			tp->t_cflag = TTYDEF_CFLAG;
97 			tp->t_lflag = TTYDEF_LFLAG;
98 			tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
99 		}
100 		cnparam(tp, &tp->t_termios);
101 		ttsetwater(tp);
102 	}
103 	/*
104 	 * Wait receiver and status interrupt
105 	 */
106 	(void) cnmctl(CN_ON, DMSET);
107 	tp->t_state |= TS_CARR_ON;
108 	return ((*linesw[tp->t_line].l_open)(dev, tp));
109 }
110 
111 /*
112  * Close console.
113  */
114 /*ARGSUSED*/
115 cnclose(dev, flag)
116 	dev_t dev;
117 	int flag;
118 {
119 	register struct tty *tp = &cn_tty[0];
120 
121 	(*linesw[tp->t_line].l_close)(tp);
122 	(void) cnmctl(CN_BRK, DMBIC);
123 	ttyclose(tp);
124 	return (0);
125 }
126 
127 /*ARGSUSED*/
128 cnread(dev, uio, flag)
129 	dev_t dev;
130 	struct uio *uio;
131 	int flag;
132 {
133 	register struct tty *tp = &cn_tty[0];
134 
135 	return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
136 }
137 
138 /*ARGSUSED*/
139 cnwrite(dev, uio, flag)
140 	dev_t dev;
141 	struct uio *uio;
142 	int flag;
143 {
144 	register struct tty *tp = &cn_tty[0];
145 
146 	return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
147 }
148 
149 /*
150  * console receiver interrupt.
151  */
152 _cnrint(buf, n)
153 	register char *buf;
154 	register int n;
155 {
156 	register struct tty *tp = &cn_tty[0];
157 	register int (*rint)();
158 
159 	if ((tp->t_state & TS_ISOPEN) == 0) {
160 		wakeup((caddr_t)&tp->t_rawq);
161 		cn_enable();
162 		return;
163 	}
164 	/*
165 	 * Loop fetching characters from the silo for console
166 	 * until there are no more in the silo.
167 	 */
168 	rint = linesw[tp->t_line].l_rint;
169 	while (--n >= 0)
170 		(*rint)(*buf++, tp);
171 	cn_enable();
172 }
173 
174 /*
175  * Ioctl for console.
176  */
177 /*ARGSUSED*/
178 cnioctl(dev, cmd, data, flag)
179 	dev_t dev;
180 	caddr_t data;
181 {
182 	register struct tty *tp = &cn_tty[0];
183 	int error;
184 
185 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
186 	if (error >= 0)
187 		return (error);
188 	error = ttioctl(tp, cmd, data, flag);
189 	if (error >= 0)
190 		return (error);
191 
192 	switch (cmd) {
193 
194 	case TIOCSBRK:
195 		(void) cnmctl(CN_BRK, DMBIS);
196 		break;
197 
198 	case TIOCCBRK:
199 		(void) cnmctl(CN_BRK, DMBIC);
200 		break;
201 
202 	case TIOCSDTR:
203 		(void) cnmctl(CN_DTR|CN_RTS, DMBIS);
204 		break;
205 
206 	case TIOCCDTR:
207 		(void) cnmctl(CN_DTR|CN_RTS, DMBIC);
208 		break;
209 
210 	case TIOCMSET:
211 		(void) cnmctl(dmtocn(*(int *)data), DMSET);
212 		break;
213 
214 	case TIOCMBIS:
215 		(void) cnmctl(dmtocn(*(int *)data), DMBIS);
216 		break;
217 
218 	case TIOCMBIC:
219 		(void) cnmctl(dmtocn(*(int *)data), DMBIC);
220 		break;
221 
222 	case TIOCMGET:
223 		*(int *)data = cntodm(cnmctl(0, DMGET));
224 		break;
225 
226 	default:
227 		return (ENOTTY);
228 	}
229 	return (0);
230 }
231 
232 dmtocn(bits)
233 	register int bits;
234 {
235 	register int b;
236 
237 	b = 0;
238 	if (bits & DML_LE)  b |= CN_TXE|CN_RXE;
239 	if (bits & DML_DTR) b |= CN_DTR;
240 	if (bits & DML_RTS) b |= CN_RTS;
241 	if (bits & DML_CTS) b |= CN_CTS;
242 	if (bits & DML_CAR) b |= CN_DCD;
243 	if (bits & DML_RNG) b |= CN_RI;
244 	if (bits & DML_DSR) b |= CN_DSR;
245 	return(b);
246 }
247 
248 cntodm(bits)
249 	register int bits;
250 {
251 	register int b;
252 
253 	b = 0;
254 	if (bits & (CN_TXE|CN_RXE)) b |= DML_LE;
255 	if (bits & CN_DTR) b |= DML_DTR;
256 	if (bits & CN_RTS) b |= DML_RTS;
257 	if (bits & CN_CTS) b |= DML_CTS;
258 	if (bits & CN_DCD) b |= DML_CAR;
259 	if (bits & CN_RI)  b |= DML_RNG;
260 	if (bits & CN_DSR) b |= DML_DSR;
261 	return(b);
262 }
263 
264 /*
265  * Set parameters from open or stty into the console hardware
266  * registers.
267  */
268 cnparam(tp, t)
269 	register struct tty *tp;
270 	register struct termios *t;
271 {
272 	register int param;
273 	register int cflag = t->c_cflag;
274 	int s;
275 
276 	/*
277 	 * Block interrupts so parameters will be set
278 	 * before the line interrupts.
279 	 */
280 	s = splcons();
281 	if ((tp->t_ispeed)==0) {
282 		tp->t_cflag |= HUPCL;
283 		(void) cnmctl(CN_OFF, DMSET);
284 		(void) splx(s);
285 		return;
286 	}
287 
288 	param = cn_get_param() &
289 		~(CHAR_SIZE|PARITY|EVEN|STOPBIT|BAUD_RATE|NOCHECK);
290 	if ((cflag & CREAD) == 0)
291 		param &= ~RXE;
292 	switch (cflag & CSIZE) {
293 	    case CS5: break;
294 	    case CS6: param |= C6BIT; break;
295 	    case CS7: param |= C7BIT; break;
296 	    case CS8: param |= C8BIT; break;
297 	}
298 	if (cflag & PARENB)
299 		param |= PARITY;
300 	if ((cflag & PARODD) == 0)
301 		param |= EVEN;
302 	if ((tp->t_iflag & INPCK) == 0)
303 		param |= NOCHECK;
304 	if (cflag & CSTOPB)
305 		param |= STOP2;
306 	else
307 		param |= STOP1;
308 	cn_set_param(param);
309 	(void) splx(s);
310 }
311 
312 /*
313  * console transmitter interrupt.
314  * Restart the idle line.
315  */
316 _cnxint(count)
317 	int count;
318 {
319 	register struct tty *tp = &cn_tty[0];
320 	int s;
321 
322 	cn_stopped[0] = 0;
323 	tp->t_state &= ~TS_BUSY;
324 	s = splcons();
325 	if (tp->t_state & TS_FLUSH)
326 		tp->t_state &= ~TS_FLUSH;
327 	else
328 		ndflush(&tp->t_outq, count);
329 	(void) splx(s);
330 	if (tp->t_line)
331 		(*linesw[tp->t_line].l_start)(tp);
332 	else
333 		cnstart(tp);
334 }
335 
336 /*
337  * Start (restart) transmission on the console.
338  */
339 void
340 cnstart(tp)
341 	register struct tty *tp;
342 {
343 	register int nch;
344 	int s;
345 
346 	/*
347 	 * Must hold interrupts in following code to prevent
348 	 * state of the tp from changing.
349 	 */
350 	s = splcons();
351 	/*
352 	 * If it's currently active, or delaying, no need to do anything.
353 	 */
354 	if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
355 		goto out;
356 	/*
357 	 * If ther are still characters in the IOP,
358 	 * just reenable transmit.
359 	 */
360 	if (cn_stopped[0]) {
361 		cn_stopped[0] = 0;
362 		cn_start();
363 		goto out;
364 	}
365 	/*
366 	 * If there are sleepers, and output has drained below low
367 	 * water mark, wake up the sleepers.
368 	 */
369 	if (tp->t_outq.c_cc <= tp->t_lowat) {
370 		if (tp->t_state & TS_ASLEEP) {
371 			tp->t_state &= ~TS_ASLEEP;
372 			wakeup((caddr_t)&tp->t_outq);
373 		}
374 		selwakeup(&tp->t_wsel);
375 	}
376 	/*
377 	 * Now restart transmission unless the output queue is
378 	 * empty.
379 	 */
380 	if (tp->t_outq.c_cc == 0)
381 		goto out;
382 	if (tp->t_flags & (RAW|LITOUT))
383 		nch = ndqb(&tp->t_outq, 0);
384 	else {
385 		nch = ndqb(&tp->t_outq, 0200);
386 		/*
387 		 * If first thing on queue is a delay process it.
388 		 */
389 		if (nch == 0) {
390 			nch = getc(&tp->t_outq);
391 			timeout(ttrstrt, (caddr_t)tp, (nch&0x7f)+6);
392 			tp->t_state |= TS_TIMEOUT;
393 			goto out;
394 		}
395 	}
396 	/*
397 	 * If characters to transmit, restart transmission.
398 	 */
399 	if (nch) {
400 		tp->t_state |= TS_BUSY;
401 		cn_output(tp, nch);
402 	}
403 out:
404 	(void) splx(s);
405 }
406 
407 /*
408  * Stop output on a line, e.g. for ^S/^Q or output flush.
409  */
410 /*ARGSUSED*/
411 cnstop(tp, flag)
412 	register struct tty *tp;
413 {
414 	register int s;
415 
416 	/*
417 	 * Block input/output interrupts while messing with state.
418 	 */
419 	s = splcons();
420 	if (tp->t_state & TS_BUSY) {
421 		cn_stop(0);
422 		cn_stopped[0] = 1;
423 		if ((tp->t_state & TS_TTSTOP) == 0) {
424 			tp->t_state |= TS_FLUSH;
425 			cn_stop(1);
426 		}
427 	}
428 	(void) splx(s);
429 }
430 
431 /*
432  * console modem control
433  */
434 cnmctl(bits, how)
435 	int bits, how;
436 {
437 	register int mbits;
438 	int s;
439 
440 	bits &= (RXE|TXE|RTS|DTR|XBREAK);
441 
442 	s = splcons();
443 
444 	mbits = cn_get_param();
445 	switch (how) {
446 	case DMSET:
447 		mbits = mbits & ~(RXE|TXE|RTS|DTR|XBREAK) | bits;
448 		break;
449 
450 	case DMBIS:
451 		mbits |= bits;
452 		break;
453 
454 	case DMBIC:
455 		mbits &= ~bits;
456 		break;
457 
458 	case DMGET:
459 		(void) splx(s);
460 		return(mbits);
461 	}
462 	cn_set_param(mbits);
463 
464 	(void) splx(s);
465 	return(mbits);
466 }
467 
468 /*
469  * console status interrupt
470  */
471 _cnsint(stat)
472 	int stat;
473 {
474 	register struct tty *tp = &cn_tty[0];
475 
476 	if (stat & OVERRUN_ERROR)
477 		printf("console: fifo overflow\n");
478 	if (stat & RBREAK)
479 		(*linesw[tp->t_line].l_rint)
480 		    (tp->t_flags & RAW ? '\0' : tp->t_cc[VINTR], tp);
481 }
482 
483 /*
484  * console control interrupt
485  */
486 cncint()
487 {
488 	printf("cncint:\n");
489 }
490 
491 /*
492  * Machine dependent functions
493  *
494  *	cn_init()
495  *	cnrint()
496  *	cnxint()
497  *	cnsint()
498  *	cn_enable()
499  *	cn_output()
500  *	cn_start()
501  *	cn_stop()
502  *	cn_get_param()
503  *	cn_set_param()
504  */
505 #ifdef IPC_MRX
506 #include <news3400/newsipc/newsipc.h>
507 #include <news3400/mrx/h/cio.h>
508 #include <news3400/mrx/h/console.h>
509 
510 #ifdef mips
511 #define ipc_phys(x)	K0_TT0(x)
512 #define ipc_log(x)	TT0_K0(x)
513 #else
514 #define ipc_phys(x)	(caddr_t)((int)(x) & ~0x80000000)
515 #define ipc_log(x)	(caddr_t)((int)(x) | 0x80000000)
516 #endif
517 
518 #if NBM > 0
519 extern char *ext_fnt_addr[];
520 extern char *ext_fnt24_addr[];
521 #endif /* NBM > 0 */
522 
523 int	port_cnrecv;
524 int	port_cnxmit;
525 int	port_cnstat;
526 int	port_cnctrl;
527 int	port_cnfont;
528 int	port_cnrecv_iop;
529 int	port_cnxmit_iop;
530 int	port_cnstat_iop;
531 int	port_cnctrl_iop;
532 
533 int	cnfont();
534 
535 cn_init()
536 {
537 	struct cons_ctrl_req req;
538 	int *reply;
539 
540 	port_cnrecv = port_create("@cnrecv", cnrint, -1);
541 	port_cnxmit = port_create("@cnxmit", cnxint, -1);
542 	port_cnctrl = port_create("@cnctrl", NULL, 0);
543 	port_cnstat = port_create("@cnstat", cnsint, -1);
544 	port_cnfont = port_create("@cnfont", cnfont, -1);
545 
546 	/* use NULL action port */
547 	port_cnrecv_iop = object_query("cons_input");
548 	port_cnxmit_iop = object_query("cons_output");
549 	port_cnctrl_iop = object_query("cons_ctrl");
550 	port_cnstat_iop = object_query("cons_stat");
551 	req.cons_func = CIO_ASKDEVICE;
552 	msg_send(port_cnctrl_iop, port_cnctrl, &req, sizeof(req), 0);
553 	msg_recv(port_cnctrl, NULL, &reply, NULL, 0);
554 	tty00_is_console = *reply;
555 	msg_free(port_cnctrl);
556 #if NBM > 0
557 	req.cons_func = CIO_SET16FNT;
558 	req.cons_addr = (char *)ipc_phys(ext_fnt_addr);
559 	msg_send(port_cnctrl_iop, port_cnctrl, &req, sizeof(req), 0);
560 	msg_recv(port_cnctrl, NULL, NULL, NULL, 0);
561 	req.cons_func = CIO_SET24FNT;
562 	req.cons_addr = (char *)ipc_phys(ext_fnt24_addr);
563 	msg_send(port_cnctrl_iop, port_cnctrl, &req, sizeof(req), 0);
564 	msg_recv(port_cnctrl, NULL, NULL, NULL, 0);
565 #endif
566 	return (0);
567 }
568 
569 cn_enable()
570 {
571 	int len;
572 
573 	len = MAX_CIO;
574 	msg_send(port_cnrecv_iop, port_cnrecv, &len, sizeof(len), 0);
575 }
576 
577 cnrint(port)
578 	int port;
579 {
580 	int len;
581 	char *buf;
582 
583 	msg_recv(port, NULL, &buf, &len, 0);
584 #ifdef mips
585 	_cnrint((char *)MACH_CACHED_TO_UNCACHED(buf), len);
586 #else
587 	dcia();
588 	_cnrint(buf, len);
589 #endif
590 	msg_free(port);
591 }
592 
593 cnxint(port)
594 	int port;
595 {
596 	int *len;
597 
598 	msg_recv(port, NULL, &len, NULL, 0);
599 	_cnxint(*len);
600 }
601 
602 cn_start()
603 {
604 	int func;
605 
606 	func = CIO_START;
607 	msg_send(port_cnctrl_iop, 0, &func, sizeof(func), 0);
608 }
609 
610 cn_output(tp, n)
611 	struct tty *tp;
612 	int n;
613 {
614 
615 	msg_send(port_cnxmit_iop, port_cnxmit, tp->t_outq.c_cf,
616 	    min(n, MAX_CIO), 0);
617 }
618 
619 cn_stop(flush)
620 	int flush;
621 {
622 	int	func;
623 
624 	func = flush ? CIO_FLUSH : CIO_STOP;
625 	msg_send(port_cnctrl_iop, 0, &func, sizeof(func), 0);
626 }
627 
628 cnsint(port)
629 	int port;
630 {
631 	int *stat;
632 
633 	msg_recv(port, NULL, &stat, NULL, 0);
634 	_cnsint(*stat);
635 	msg_send(port_cnstat_iop, port_cnstat, NULL, 0, 0);
636 }
637 
638 cn_get_param()
639 {
640 	struct cons_ctrl_req req;
641 	int *reply, param;
642 
643 	req.cons_func = CIO_GETPARAMS;
644 	/* message length 8 means 2 * sizeof(int) : func and status */
645 	msg_send(port_cnctrl_iop, port_cnctrl, &req, 8, 0);
646 	msg_recv(port_cnctrl, NULL, &reply, NULL, 0);
647 	param = *reply;
648 	msg_free(port_cnctrl);
649 
650 	return (param);
651 }
652 
653 cn_set_param(param)
654 	int param;
655 {
656 	struct cons_ctrl_req req;
657 
658 	req.cons_func = CIO_SETPARAMS;
659 	req.cons_status = param;
660 
661 	/* message length 8 means 2 * sizeof(int) : func and status */
662 	msg_send(port_cnctrl_iop, 0, &req, 8, 0);
663 }
664 
665 cnfont(port)
666 	int port;
667 {
668 	int *func;
669 
670 	msg_recv(port, NULL, &func, NULL, 0);
671 #if NBM > 0
672 	switch (*func) {
673 
674 	case FONT_JISROMAN:
675 		font_jisroman();
676 		font_jisroman24();
677 		break;
678 
679 	case FONT_ASCII:
680 		font_ascii();
681 		font_ascii24();
682 		break;
683 	}
684 #endif /* NBM > 0 */
685 	msg_free(port);
686 }
687 #endif /* IPC_MRX */
688 
689 #ifdef CPU_SINGLE
690 #include <news3400/hbdev/rsreg.h>
691 #include <news3400/iop/framebuf.h>
692 #include <news3400/fb/fbdefs.h>
693 
694 int lastcount;
695 int start_dimmer = 1;
696 
697 cn_init()
698 {
699 
700 	if (start_dimmer) {
701 		auto_dimmer();
702 		start_dimmer = 0;
703 	}
704 	return (0);
705 }
706 
707 cn_enable()
708 {
709 
710 	/* nothing to do */
711 }
712 
713 cnrint(code)
714 	char code;
715 {
716 
717 	_cnrint(&code, 1);
718 }
719 
720 cnxint()
721 {
722 
723 	_cnxint(lastcount);
724 }
725 
726 cn_start()
727 {
728 
729 	/* nothing to do */
730 }
731 
732 cn_output(tp, n)
733 	struct tty *tp;
734 	int n;
735 {
736 
737 	lastcount = vt100_write(0, tp->t_outq.c_cf, n);
738 	cnxint();
739 }
740 
741 cn_stop(flush)
742 	int flush;
743 {
744 
745 	/* nothing to do */
746 }
747 
748 cnsint(param)
749 	int param;
750 {
751 
752 	_cnsint(param);
753 }
754 
755 cn_get_param()
756 {
757 
758 	return (bitmap_get_param());
759 }
760 
761 cn_set_param(param)
762 	int param;
763 {
764 
765 	bitmap_set_param(param);
766 }
767 #endif /* CPU_SINGLE */
768