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.8 (Berkeley) 12/16/90 8 */ 9 10 #include "dca.h" 11 #if NDCA > 0 12 /* 13 * 98626/98644/internal serial interface 14 */ 15 #include "sys/param.h" 16 #include "sys/systm.h" 17 #include "sys/ioctl.h" 18 #include "sys/tty.h" 19 #include "sys/user.h" 20 #include "sys/conf.h" 21 #include "sys/file.h" 22 #include "sys/uio.h" 23 #include "sys/kernel.h" 24 #include "sys/syslog.h" 25 26 #include "device.h" 27 #include "dcareg.h" 28 #include "../include/cpu.h" 29 #include "../hp300/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 = 0; 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 tp->t_state |= TS_WOPEN; 146 ttychars(tp); 147 tp->t_iflag = TTYDEF_IFLAG; 148 tp->t_oflag = TTYDEF_OFLAG; 149 tp->t_cflag = TTYDEF_CFLAG; 150 tp->t_lflag = TTYDEF_LFLAG; 151 tp->t_ispeed = tp->t_ospeed = dcadefaultrate; 152 dcaparam(tp, &tp->t_termios); 153 ttsetwater(tp); 154 } else if (tp->t_state&TS_XCLUDE && u.u_uid != 0) 155 return (EBUSY); 156 (void) dcamctl(dev, MCR_DTR | MCR_RTS, DMSET); 157 if ((dcasoftCAR & (1 << unit)) || (dcamctl(dev, 0, DMGET) & MSR_DCD)) 158 tp->t_state |= TS_CARR_ON; 159 (void) spltty(); 160 while ((flag&O_NONBLOCK) == 0 && (tp->t_cflag&CLOCAL) == 0 && 161 (tp->t_state & TS_CARR_ON) == 0) { 162 tp->t_state |= TS_WOPEN; 163 if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH, 164 ttopen, 0)) 165 break; 166 } 167 (void) spl0(); 168 if (error == 0) 169 error = (*linesw[tp->t_line].l_open)(dev, tp); 170 return (error); 171 } 172 173 /*ARGSUSED*/ 174 dcaclose(dev, flag) 175 dev_t dev; 176 { 177 register struct tty *tp; 178 register struct dcadevice *dca; 179 register int unit; 180 181 unit = UNIT(dev); 182 dca = dca_addr[unit]; 183 tp = &dca_tty[unit]; 184 (*linesw[tp->t_line].l_close)(tp); 185 dca->dca_cfcr &= ~CFCR_SBREAK; 186 #ifdef KGDB 187 /* do not disable interrupts if debugging */ 188 if (kgdb_dev != makedev(1, unit)) 189 #endif 190 dca->dca_ier = 0; 191 if (tp->t_cflag&HUPCL || tp->t_state&TS_WOPEN || 192 (tp->t_state&TS_ISOPEN) == 0) 193 (void) dcamctl(dev, 0, DMSET); 194 ttyclose(tp); 195 return(0); 196 } 197 198 dcaread(dev, uio, flag) 199 dev_t dev; 200 struct uio *uio; 201 { 202 register struct tty *tp = &dca_tty[UNIT(dev)]; 203 204 return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 205 } 206 207 dcawrite(dev, uio, flag) 208 dev_t dev; 209 struct uio *uio; 210 { 211 int unit = UNIT(dev); 212 register struct tty *tp = &dca_tty[unit]; 213 214 /* 215 * (XXX) We disallow virtual consoles if the physical console is 216 * a serial port. This is in case there is a display attached that 217 * is not the console. In that situation we don't need/want the X 218 * server taking over the console. 219 */ 220 if (constty && unit == dcaconsole) 221 constty = NULL; 222 return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 223 } 224 225 dcaintr(unit) 226 register int unit; 227 { 228 register struct dcadevice *dca; 229 register u_char code; 230 register struct tty *tp; 231 232 dca = dca_addr[unit]; 233 if ((dca->dca_ic & IC_IR) == 0) 234 return(0); 235 while (1) { 236 code = dca->dca_iir; 237 switch (code) { 238 case IIR_NOPEND: 239 return (1); 240 case IIR_RXRDY: 241 /* do time-critical read in-line */ 242 tp = &dca_tty[unit]; 243 code = dca->dca_data; 244 if ((tp->t_state & TS_ISOPEN) == 0) { 245 #ifdef KGDB 246 if (kgdb_dev == makedev(1, unit) && 247 code == '!') { 248 printf("kgdb trap from dca%d\n", unit); 249 /* trap into kgdb */ 250 asm("trap #15;"); 251 } 252 #endif 253 } else 254 (*linesw[tp->t_line].l_rint)(code, tp); 255 break; 256 case IIR_TXRDY: 257 tp = &dca_tty[unit]; 258 tp->t_state &=~ (TS_BUSY|TS_FLUSH); 259 if (tp->t_line) 260 (*linesw[tp->t_line].l_start)(tp); 261 else 262 dcastart(tp); 263 break; 264 case IIR_RLS: 265 dcaeint(unit, dca); 266 break; 267 default: 268 if (code & IIR_NOPEND) 269 return (1); 270 log(LOG_WARNING, "dca%d: weird interrupt: 0x%x\n", 271 unit, code); 272 /* fall through */ 273 case IIR_MLSC: 274 dcamint(unit, dca); 275 break; 276 } 277 } 278 } 279 280 dcaeint(unit, dca) 281 register int unit; 282 register struct dcadevice *dca; 283 { 284 register struct tty *tp; 285 register int stat, c; 286 287 tp = &dca_tty[unit]; 288 stat = dca->dca_lsr; 289 c = dca->dca_data; 290 if ((tp->t_state & TS_ISOPEN) == 0) { 291 #ifdef KGDB 292 /* we don't care about parity errors */ 293 if (((stat & (LSR_BI|LSR_FE|LSR_PE)) == LSR_PE) && 294 kgdb_dev == makedev(1, unit) && c == '!') { 295 printf("kgdb trap from dca%d\n", unit); 296 /* trap into kgdb */ 297 asm("trap #15;"); 298 } 299 #endif 300 return; 301 } 302 if (stat & (LSR_BI | LSR_FE)) 303 c |= TTY_FE; 304 else if (stat & LSR_PE) 305 c |= TTY_PE; 306 else if (stat & LSR_OE) 307 log(LOG_WARNING, "dca%d: silo overflow\n", unit); 308 (*linesw[tp->t_line].l_rint)(c, tp); 309 } 310 311 dcamint(unit, dca) 312 register int unit; 313 register struct dcadevice *dca; 314 { 315 register struct tty *tp; 316 register int stat; 317 318 tp = &dca_tty[unit]; 319 stat = dca->dca_msr; 320 if ((stat & MSR_DDCD) && (dcasoftCAR & (1 << unit)) == 0) { 321 if (stat & MSR_DCD) 322 (void)(*linesw[tp->t_line].l_modem)(tp, 1); 323 else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0) 324 dca->dca_mcr &= ~(MCR_DTR | MCR_RTS); 325 } else if ((stat & MSR_DCTS) && (tp->t_state & TS_ISOPEN) && 326 (tp->t_flags & CRTSCTS)) { 327 /* the line is up and we want to do rts/cts flow control */ 328 if (stat & MSR_CTS) { 329 tp->t_state &=~ TS_TTSTOP; 330 ttstart(tp); 331 } else 332 tp->t_state |= TS_TTSTOP; 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_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 if (dca->dca_lsr & LSR_TXRDY) { 466 c = getc(&tp->t_outq); 467 tp->t_state |= TS_BUSY; 468 dca->dca_data = c; 469 } 470 out: 471 splx(s); 472 } 473 474 /* 475 * Stop output on a line. 476 */ 477 /*ARGSUSED*/ 478 dcastop(tp, flag) 479 register struct tty *tp; 480 { 481 register int s; 482 483 s = spltty(); 484 if (tp->t_state & TS_BUSY) { 485 if ((tp->t_state&TS_TTSTOP)==0) 486 tp->t_state |= TS_FLUSH; 487 } 488 splx(s); 489 } 490 491 dcamctl(dev, bits, how) 492 dev_t dev; 493 int bits, how; 494 { 495 register struct dcadevice *dca; 496 register int unit; 497 int s; 498 499 unit = UNIT(dev); 500 dca = dca_addr[unit]; 501 s = spltty(); 502 switch (how) { 503 504 case DMSET: 505 dca->dca_mcr = bits; 506 break; 507 508 case DMBIS: 509 dca->dca_mcr |= bits; 510 break; 511 512 case DMBIC: 513 dca->dca_mcr &= ~bits; 514 break; 515 516 case DMGET: 517 bits = dca->dca_msr; 518 break; 519 } 520 (void) splx(s); 521 return(bits); 522 } 523 524 /* 525 * Following are all routines needed for DCA to act as console 526 */ 527 #include "../hp300/cons.h" 528 529 dcacnprobe(cp) 530 struct consdev *cp; 531 { 532 int unit, i; 533 extern int dcaopen(); 534 535 /* XXX: ick */ 536 unit = CONUNIT; 537 dca_addr[CONUNIT] = CONADDR; 538 539 /* make sure hardware exists */ 540 if (badaddr((short *)dca_addr[unit])) { 541 cp->cn_pri = CN_DEAD; 542 return; 543 } 544 545 /* locate the major number */ 546 for (i = 0; i < nchrdev; i++) 547 if (cdevsw[i].d_open == dcaopen) 548 break; 549 550 /* initialize required fields */ 551 cp->cn_dev = makedev(i, unit); 552 cp->cn_tp = &dca_tty[unit]; 553 switch (dca_addr[unit]->dca_irid) { 554 case DCAID0: 555 case DCAID1: 556 cp->cn_pri = CN_NORMAL; 557 break; 558 case DCAREMID0: 559 case DCAREMID1: 560 cp->cn_pri = CN_REMOTE; 561 break; 562 default: 563 cp->cn_pri = CN_DEAD; 564 break; 565 } 566 } 567 568 dcacninit(cp) 569 struct consdev *cp; 570 { 571 int unit = UNIT(cp->cn_dev); 572 573 dcainit(unit); 574 dcaconsole = unit; 575 } 576 577 dcainit(unit) 578 int unit; 579 { 580 register struct dcadevice *dca; 581 int s, rate; 582 short stat; 583 584 #ifdef lint 585 stat = unit; if (stat) return; 586 #endif 587 dca = dca_addr[unit]; 588 s = splhigh(); 589 dca->dca_irid = 0xFF; 590 DELAY(100); 591 dca->dca_ic = IC_IE; 592 dca->dca_cfcr = CFCR_DLAB; 593 rate = ttspeedtab(dcadefaultrate, dcaspeedtab); 594 dca->dca_data = rate & 0xFF; 595 dca->dca_ier = rate >> 8; 596 dca->dca_cfcr = CFCR_8BITS; 597 dca->dca_ier = IER_ERXRDY | IER_ETXRDY; 598 stat = dca->dca_iir; 599 splx(s); 600 } 601 602 dcacngetc(dev) 603 { 604 register struct dcadevice *dca = dca_addr[UNIT(dev)]; 605 short stat; 606 int c, s; 607 608 #ifdef lint 609 stat = dev; if (stat) return(0); 610 #endif 611 s = splhigh(); 612 while (((stat = dca->dca_lsr) & LSR_RXRDY) == 0) 613 ; 614 c = dca->dca_data; 615 stat = dca->dca_iir; 616 splx(s); 617 return(c); 618 } 619 620 /* 621 * Console kernel output character routine. 622 */ 623 dcacnputc(dev, c) 624 dev_t dev; 625 register int c; 626 { 627 register struct dcadevice *dca = dca_addr[UNIT(dev)]; 628 register int timo; 629 short stat; 630 int s = splhigh(); 631 632 #ifdef lint 633 stat = dev; if (stat) return; 634 #endif 635 if (dcaconsole == -1) { 636 (void) dcainit(UNIT(dev)); 637 dcaconsole = UNIT(dev); 638 } 639 /* wait for any pending transmission to finish */ 640 timo = 50000; 641 while (((stat = dca->dca_lsr) & LSR_TXRDY) == 0 && --timo) 642 ; 643 dca->dca_data = c; 644 /* wait for this transmission to complete */ 645 timo = 1500000; 646 while (((stat = dca->dca_lsr) & LSR_TXRDY) == 0 && --timo) 647 ; 648 /* clear any interrupts generated by this transmission */ 649 stat = dca->dca_iir; 650 splx(s); 651 } 652 #endif 653