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