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