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