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
bmattach(i)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*/
cnopen(dev,flag,mode,p)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*/
cnclose(dev,flag)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*/
cnread(dev,uio,flag)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*/
cnwrite(dev,uio,flag)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 */
_cnrint(buf,n)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*/
cnioctl(dev,cmd,data,flag)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
dmtocn(bits)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
cntodm(bits)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 */
cnparam(tp,t)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 */
_cnxint(count)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
cnstart(tp)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*/
cnstop(tp,flag)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 */
cnmctl(bits,how)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 */
_cnsint(stat)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 */
cncint()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
cn_init()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
cn_enable()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
cnrint(port)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
cnxint(port)593 cnxint(port)
594 int port;
595 {
596 int *len;
597
598 msg_recv(port, NULL, &len, NULL, 0);
599 _cnxint(*len);
600 }
601
cn_start()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
cn_stop(flush)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
cnsint(port)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
cn_get_param()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
cn_set_param(param)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
cnfont(port)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
cn_init()697 cn_init()
698 {
699
700 if (start_dimmer) {
701 auto_dimmer();
702 start_dimmer = 0;
703 }
704 return (0);
705 }
706
cn_enable()707 cn_enable()
708 {
709
710 /* nothing to do */
711 }
712
cnrint(code)713 cnrint(code)
714 char code;
715 {
716
717 _cnrint(&code, 1);
718 }
719
cnxint()720 cnxint()
721 {
722
723 _cnxint(lastcount);
724 }
725
cn_start()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
cn_stop(flush)741 cn_stop(flush)
742 int flush;
743 {
744
745 /* nothing to do */
746 }
747
cnsint(param)748 cnsint(param)
749 int param;
750 {
751
752 _cnsint(param);
753 }
754
cn_get_param()755 cn_get_param()
756 {
757
758 return (bitmap_get_param());
759 }
760
cn_set_param(param)761 cn_set_param(param)
762 int param;
763 {
764
765 bitmap_set_param(param);
766 }
767 #endif /* CPU_SINGLE */
768