1 /* 2 * Copyright (c) 1982, 1986, 1990 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)dca.c 7.3 (Berkeley) 06/06/90 8 */ 9 10 #include "dca.h" 11 #if NDCA > 0 12 /* 13 * 98626/98644/internal serial interface 14 */ 15 #include "param.h" 16 #include "systm.h" 17 #include "ioctl.h" 18 #include "tty.h" 19 #include "user.h" 20 #include "conf.h" 21 #include "file.h" 22 #include "uio.h" 23 #include "kernel.h" 24 #include "syslog.h" 25 26 #include "device.h" 27 #include "dcareg.h" 28 #include "machine/cpu.h" 29 #include "machine/isr.h" 30 31 int dcaprobe(); 32 struct driver dcadriver = { 33 dcaprobe, "dca", 34 }; 35 36 int dcastart(), dcaparam(), dcaintr(); 37 int dcasoftCAR; 38 int dca_active; 39 int ndca = NDCA; 40 int dcaconsole = -1; 41 int dcadefaultrate = TTYDEF_SPEED; 42 struct dcadevice *dca_addr[NDCA]; 43 struct tty dca_tty[NDCA]; 44 struct isr dcaisr[NDCA]; 45 46 struct speedtab dcaspeedtab[] = { 47 0, 0, 48 50, DCABRD(50), 49 75, DCABRD(75), 50 110, DCABRD(110), 51 134, DCABRD(134), 52 150, DCABRD(150), 53 200, DCABRD(200), 54 300, DCABRD(300), 55 600, DCABRD(600), 56 1200, DCABRD(1200), 57 1800, DCABRD(1800), 58 2400, DCABRD(2400), 59 4800, DCABRD(4800), 60 9600, DCABRD(9600), 61 19200, DCABRD(19200), 62 38400, DCABRD(38400), 63 -1, -1 64 }; 65 66 extern struct tty *constty; 67 #ifdef KGDB 68 extern int kgdb_dev; 69 extern int kgdb_rate; 70 extern int kgdb_debug_init; 71 #endif 72 73 #define UNIT(x) minor(x) 74 75 dcaprobe(hd) 76 register struct hp_device *hd; 77 { 78 register struct dcadevice *dca; 79 register int unit; 80 81 dca = (struct dcadevice *)hd->hp_addr; 82 if (dca->dca_irid != DCAID0 && 83 dca->dca_irid != DCAREMID0 && 84 dca->dca_irid != DCAID1 && 85 dca->dca_irid != DCAREMID1) 86 return (0); 87 unit = hd->hp_unit; 88 if (unit == dcaconsole) 89 DELAY(100000); 90 dca->dca_irid = 0xFF; 91 DELAY(100); 92 93 hd->hp_ipl = DCAIPL(dca->dca_ic); 94 dcaisr[unit].isr_ipl = hd->hp_ipl; 95 dcaisr[unit].isr_arg = unit; 96 dcaisr[unit].isr_intr = dcaintr; 97 dca_addr[unit] = dca; 98 dca_active |= 1 << unit; 99 dcasoftCAR = hd->hp_flags; 100 isrlink(&dcaisr[unit]); 101 #ifdef KGDB 102 if (kgdb_dev == makedev(1, unit)) { 103 if (dcaconsole == unit) 104 kgdb_dev = -1; /* can't debug over console port */ 105 else { 106 (void) dcainit(unit); 107 dcaconsole = -2; /* XXX */ 108 if (kgdb_debug_init) { 109 printf("dca%d: kgdb waiting...", unit); 110 /* trap into kgdb */ 111 asm("trap #15;"); 112 printf("connected.\n"); 113 } else 114 printf("dca%d: kgdb enabled\n", unit); 115 } 116 } 117 #endif 118 dca->dca_ic = IC_IE; 119 /* 120 * Need to reset baud rate, etc. of next print so reset dcaconsole. 121 * Also make sure console is always "hardwired" 122 */ 123 if (unit == dcaconsole) { 124 dcaconsole = -1; 125 dcasoftCAR |= (1 << unit); 126 } 127 return (1); 128 } 129 130 dcaopen(dev, flag) 131 dev_t dev; 132 { 133 register struct tty *tp; 134 register int unit; 135 int error; 136 137 unit = UNIT(dev); 138 if (unit >= NDCA || (dca_active & (1 << unit)) == 0) 139 return (ENXIO); 140 tp = &dca_tty[unit]; 141 tp->t_oproc = dcastart; 142 tp->t_param = dcaparam; 143 tp->t_dev = dev; 144 if ((tp->t_state & TS_ISOPEN) == 0) { 145 ttychars(tp); 146 tp->t_iflag = TTYDEF_IFLAG; 147 tp->t_oflag = TTYDEF_OFLAG; 148 tp->t_cflag = TTYDEF_CFLAG; 149 tp->t_lflag = TTYDEF_LFLAG; 150 tp->t_ispeed = tp->t_ospeed = dcadefaultrate; 151 dcaparam(tp, &tp->t_termios); 152 ttsetwater(tp); 153 } else if (tp->t_state&TS_XCLUDE && u.u_uid != 0) 154 return (EBUSY); 155 (void) dcamctl(dev, MCR_DTR | MCR_RTS, DMSET); 156 if ((dcasoftCAR & (1 << unit)) || (dcamctl(dev, 0, DMGET) & MSR_DCD)) 157 tp->t_state |= TS_CARR_ON; 158 (void) spltty(); 159 while (!(flag&O_NONBLOCK) && !(tp->t_cflag&CLOCAL) && 160 (tp->t_state & TS_CARR_ON) == 0) { 161 tp->t_state |= TS_WOPEN; 162 if ((error = tsleep((caddr_t)&tp->t_rawq, TTIPRI | PCATCH, 163 ttopen, 0)) || 164 (error = ttclosed(tp))) { 165 tp->t_state &= ~TS_WOPEN; 166 (void) spl0(); 167 return (error); 168 } 169 } 170 (void) spl0(); 171 return ((*linesw[tp->t_line].l_open)(dev, tp)); 172 } 173 174 /*ARGSUSED*/ 175 dcaclose(dev, flag) 176 dev_t dev; 177 { 178 register struct tty *tp; 179 register struct dcadevice *dca; 180 register int unit; 181 182 unit = UNIT(dev); 183 dca = dca_addr[unit]; 184 tp = &dca_tty[unit]; 185 (*linesw[tp->t_line].l_close)(tp); 186 dca->dca_cfcr &= ~CFCR_SBREAK; 187 #ifdef KGDB 188 /* do not disable interrupts if debugging */ 189 if (kgdb_dev != makedev(1, unit)) 190 #endif 191 dca->dca_ier = 0; 192 if (tp->t_cflag&HUPCL || tp->t_state&TS_WOPEN || 193 (tp->t_state&TS_ISOPEN) == 0) 194 (void) dcamctl(dev, 0, DMSET); 195 ttyclose(tp); 196 return(0); 197 } 198 199 dcaread(dev, uio, flag) 200 dev_t dev; 201 struct uio *uio; 202 { 203 register struct tty *tp = &dca_tty[UNIT(dev)]; 204 205 return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 206 } 207 208 dcawrite(dev, uio, flag) 209 dev_t dev; 210 struct uio *uio; 211 { 212 int unit = UNIT(dev); 213 register struct tty *tp = &dca_tty[unit]; 214 215 /* 216 * (XXX) We disallow virtual consoles if the physical console is 217 * a serial port. This is in case there is a display attached that 218 * is not the console. In that situation we don't need/want the X 219 * server taking over the console. 220 */ 221 if (constty && unit == dcaconsole) 222 constty = NULL; 223 return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 224 } 225 226 dcaintr(unit) 227 register int unit; 228 { 229 register struct dcadevice *dca; 230 register int code; 231 232 dca = dca_addr[unit]; 233 if ((dca->dca_ic & IC_IR) == 0) 234 return(0); 235 while (((code = dca->dca_iir) & IIR_NOPEND) == 0) { 236 code &= IIR_IMASK; 237 if (code == IIR_RLS) 238 dcaeint(unit, dca); 239 else if (code == IIR_RXRDY) 240 dcarint(unit, dca); 241 else if (code == IIR_TXRDY) 242 dcaxint(unit, dca); 243 else 244 dcamint(unit, dca); 245 } 246 return(1); 247 } 248 249 dcaeint(unit, dca) 250 register int unit; 251 register struct dcadevice *dca; 252 { 253 register struct tty *tp; 254 register int stat, c; 255 256 tp = &dca_tty[unit]; 257 stat = dca->dca_lsr; 258 c = dca->dca_data & 0xff; 259 if ((tp->t_state & TS_ISOPEN) == 0) { 260 #ifdef KGDB 261 /* we don't care about parity errors */ 262 if (((stat & (LSR_BI|LSR_FE|LSR_PE)) == LSR_PE) && 263 kgdb_dev == makedev(1, unit) && c == '!') { 264 printf("kgdb trap from dca%d\n", unit); 265 /* trap into kgdb */ 266 asm("trap #15;"); 267 } 268 #endif 269 return; 270 } 271 if (stat & (LSR_BI | LSR_FE)) 272 c |= TTY_FE; 273 else if (stat & LSR_PE) 274 c |= TTY_PE; 275 else if (stat & LSR_OE) 276 log(LOG_WARNING, "dca%d: silo overflow\n", unit); 277 (*linesw[tp->t_line].l_rint)(c, tp); 278 } 279 280 dcarint(unit, dca) 281 int unit; 282 register struct dcadevice *dca; 283 { 284 register struct tty *tp; 285 register int c; 286 287 tp = &dca_tty[unit]; 288 c = dca->dca_data; 289 if ((tp->t_state & TS_ISOPEN) == 0) { 290 #ifdef KGDB 291 if (kgdb_dev == makedev(1, unit) && c == '!') { 292 printf("kgdb trap from dca%d\n", unit); 293 /* trap into kgdb */ 294 asm("trap #15;"); 295 } 296 #endif 297 return; 298 } 299 (*linesw[tp->t_line].l_rint)(c, tp); 300 } 301 302 /*ARGSUSED*/ 303 dcaxint(unit, dca) 304 int unit; 305 struct dcadevice *dca; 306 { 307 register struct tty *tp; 308 309 tp = &dca_tty[unit]; 310 tp->t_state &= ~TS_BUSY; 311 if (tp->t_state & TS_FLUSH) 312 tp->t_state &= ~TS_FLUSH; 313 if (tp->t_line) 314 (*linesw[tp->t_line].l_start)(tp); 315 else 316 dcastart(tp); 317 } 318 319 dcamint(unit, dca) 320 register int unit; 321 register struct dcadevice *dca; 322 { 323 register struct tty *tp; 324 register int stat; 325 326 tp = &dca_tty[unit]; 327 stat = dca->dca_msr; 328 if ((stat & MSR_CCD) && (dcasoftCAR & (1 << unit)) == 0) { 329 if (stat & MSR_DCD) 330 (void) (*linesw[tp->t_line].l_modem)(tp, 1); 331 else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0) 332 dca->dca_mcr &= ~(MCR_DTR | MCR_RTS); 333 } 334 } 335 336 dcaioctl(dev, cmd, data, flag) 337 dev_t dev; 338 caddr_t data; 339 { 340 register struct tty *tp; 341 register int unit = UNIT(dev); 342 register struct dcadevice *dca; 343 register int error; 344 345 tp = &dca_tty[unit]; 346 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); 347 if (error >= 0) 348 return (error); 349 error = ttioctl(tp, cmd, data, flag); 350 if (error >= 0) 351 return (error); 352 353 dca = dca_addr[unit]; 354 switch (cmd) { 355 356 case TIOCSBRK: 357 dca->dca_cfcr |= CFCR_SBREAK; 358 break; 359 360 case TIOCCBRK: 361 dca->dca_cfcr &= ~CFCR_SBREAK; 362 break; 363 364 case TIOCSDTR: 365 (void) dcamctl(dev, MCR_DTR | MCR_RTS, DMBIS); 366 break; 367 368 case TIOCCDTR: 369 (void) dcamctl(dev, MCR_DTR | MCR_RTS, DMBIC); 370 break; 371 372 case TIOCMSET: 373 (void) dcamctl(dev, *(int *)data, DMSET); 374 break; 375 376 case TIOCMBIS: 377 (void) dcamctl(dev, *(int *)data, DMBIS); 378 break; 379 380 case TIOCMBIC: 381 (void) dcamctl(dev, *(int *)data, DMBIC); 382 break; 383 384 case TIOCMGET: 385 *(int *)data = dcamctl(dev, 0, DMGET); 386 break; 387 388 default: 389 return (ENOTTY); 390 } 391 return (0); 392 } 393 394 dcaparam(tp, t) 395 register struct tty *tp; 396 register struct termios *t; 397 { 398 register struct dcadevice *dca; 399 register int cfcr, cflag = t->c_cflag; 400 int unit = UNIT(tp->t_dev); 401 int ospeed = ttspeedtab(t->c_ospeed, dcaspeedtab); 402 403 /* check requested parameters */ 404 if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed)) 405 return(EINVAL); 406 /* and copy to tty */ 407 tp->t_ispeed = t->c_ispeed; 408 tp->t_ospeed = t->c_ospeed; 409 tp->t_cflag = cflag; 410 411 dca = dca_addr[unit]; 412 dca->dca_ier = IER_ERXRDY | IER_ETXRDY | IER_ERLS | IER_EMSC; 413 if (ospeed == 0) { 414 (void) dcamctl(unit, 0, DMSET); /* hang up line */ 415 return(0); 416 } 417 dca->dca_cfcr |= CFCR_DLAB; 418 dca->dca_data = ospeed & 0xFF; 419 dca->dca_ier = ospeed >> 8; 420 switch (cflag&CSIZE) { 421 case CS5: 422 cfcr = CFCR_5BITS; break; 423 case CS6: 424 cfcr = CFCR_6BITS; break; 425 case CS7: 426 cfcr = CFCR_7BITS; break; 427 case CS8: 428 cfcr = CFCR_8BITS; break; 429 } 430 if (cflag&PARENB) { 431 cfcr |= CFCR_PENAB; 432 if ((cflag&PARODD) == 0) 433 cfcr |= CFCR_PEVEN; 434 } 435 if (cflag&CSTOPB) 436 cfcr |= CFCR_STOPB; 437 dca->dca_cfcr = cfcr; 438 return(0); 439 } 440 441 dcastart(tp) 442 register struct tty *tp; 443 { 444 register struct dcadevice *dca; 445 int s, unit, c; 446 447 unit = UNIT(tp->t_dev); 448 dca = dca_addr[unit]; 449 s = spltty(); 450 if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) 451 goto out; 452 if (tp->t_outq.c_cc <= tp->t_lowat) { 453 if (tp->t_state&TS_ASLEEP) { 454 tp->t_state &= ~TS_ASLEEP; 455 wakeup((caddr_t)&tp->t_outq); 456 } 457 if (tp->t_wsel) { 458 selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); 459 tp->t_wsel = 0; 460 tp->t_state &= ~TS_WCOLL; 461 } 462 } 463 if (tp->t_outq.c_cc == 0) 464 goto out; 465 c = getc(&tp->t_outq); 466 tp->t_state |= TS_BUSY; 467 dca->dca_data = c; 468 out: 469 splx(s); 470 } 471 472 /* 473 * Stop output on a line. 474 */ 475 /*ARGSUSED*/ 476 dcastop(tp, flag) 477 register struct tty *tp; 478 { 479 register int s; 480 481 s = spltty(); 482 if (tp->t_state & TS_BUSY) { 483 if ((tp->t_state&TS_TTSTOP)==0) 484 tp->t_state |= TS_FLUSH; 485 } 486 splx(s); 487 } 488 489 dcamctl(dev, bits, how) 490 dev_t dev; 491 int bits, how; 492 { 493 register struct dcadevice *dca; 494 register int unit; 495 int s; 496 497 unit = UNIT(dev); 498 dca = dca_addr[unit]; 499 s = spltty(); 500 switch (how) { 501 502 case DMSET: 503 dca->dca_mcr = bits; 504 break; 505 506 case DMBIS: 507 dca->dca_mcr |= bits; 508 break; 509 510 case DMBIC: 511 dca->dca_mcr &= ~bits; 512 break; 513 514 case DMGET: 515 bits = dca->dca_msr; 516 break; 517 } 518 (void) splx(s); 519 return(bits); 520 } 521 522 /* 523 * Following are all routines needed for DCA to act as console 524 */ 525 #include "machine/cons.h" 526 527 dcacnprobe(cp) 528 struct consdev *cp; 529 { 530 int unit, i; 531 extern int dcaopen(); 532 533 /* XXX: ick */ 534 unit = CONUNIT; 535 dca_addr[CONUNIT] = CONADDR; 536 537 /* make sure hardware exists */ 538 if (badaddr((short *)dca_addr[unit])) { 539 cp->cn_pri = CN_DEAD; 540 return; 541 } 542 543 /* locate the major number */ 544 for (i = 0; i < nchrdev; i++) 545 if (cdevsw[i].d_open == dcaopen) 546 break; 547 548 /* initialize required fields */ 549 cp->cn_dev = makedev(i, unit); 550 cp->cn_tp = &dca_tty[unit]; 551 switch (dca_addr[unit]->dca_irid) { 552 case DCAID0: 553 case DCAID1: 554 cp->cn_pri = CN_NORMAL; 555 break; 556 case DCAREMID0: 557 case DCAREMID1: 558 cp->cn_pri = CN_REMOTE; 559 break; 560 default: 561 cp->cn_pri = CN_DEAD; 562 break; 563 } 564 } 565 566 dcacninit(cp) 567 struct consdev *cp; 568 { 569 int unit = UNIT(cp->cn_dev); 570 571 dcainit(unit); 572 dcaconsole = unit; 573 } 574 575 dcainit(unit) 576 int unit; 577 { 578 register struct dcadevice *dca; 579 int s, rate; 580 short stat; 581 582 #ifdef lint 583 stat = unit; if (stat) return; 584 #endif 585 dca = dca_addr[unit]; 586 s = splhigh(); 587 dca->dca_irid = 0xFF; 588 DELAY(100); 589 dca->dca_ic = IC_IE; 590 dca->dca_cfcr = CFCR_DLAB; 591 rate = ttspeedtab(dcadefaultrate, dcaspeedtab); 592 dca->dca_data = rate & 0xFF; 593 dca->dca_ier = rate >> 8; 594 dca->dca_cfcr = CFCR_8BITS; 595 dca->dca_ier = IER_ERXRDY | IER_ETXRDY; 596 stat = dca->dca_iir; 597 splx(s); 598 } 599 600 dcacngetc(dev) 601 { 602 register struct dcadevice *dca = dca_addr[UNIT(dev)]; 603 short stat; 604 int c, s; 605 606 #ifdef lint 607 stat = dev; if (stat) return(0); 608 #endif 609 s = splhigh(); 610 while (((stat = dca->dca_lsr) & LSR_RXRDY) == 0) 611 ; 612 c = dca->dca_data; 613 stat = dca->dca_iir; 614 splx(s); 615 return(c); 616 } 617 618 /* 619 * Console kernel output character routine. 620 */ 621 dcacnputc(dev, c) 622 dev_t dev; 623 register int c; 624 { 625 register struct dcadevice *dca = dca_addr[UNIT(dev)]; 626 register int timo; 627 short stat; 628 int s = splhigh(); 629 630 #ifdef lint 631 stat = dev; if (stat) return; 632 #endif 633 if (dcaconsole == -1) { 634 (void) dcainit(UNIT(dev)); 635 dcaconsole = UNIT(dev); 636 } 637 /* wait for any pending transmission to finish */ 638 timo = 50000; 639 while (((stat = dca->dca_lsr) & LSR_TXRDY) == 0 && --timo) 640 ; 641 dca->dca_data = c; 642 /* wait for this transmission to complete */ 643 timo = 1500000; 644 while (((stat = dca->dca_lsr) & LSR_TXRDY) == 0 && --timo) 645 ; 646 /* clear any interrupts generated by this transmission */ 647 stat = dca->dca_iir; 648 splx(s); 649 } 650 #endif 651