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