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