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