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.1 (Berkeley) 05/08/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 136 unit = UNIT(dev); 137 if (unit >= NDCA || (dca_active & (1 << unit)) == 0) 138 return (ENXIO); 139 tp = &dca_tty[unit]; 140 tp->t_oproc = dcastart; 141 tp->t_param = dcaparam; 142 tp->t_dev = dev; 143 if ((tp->t_state & TS_ISOPEN) == 0) { 144 ttychars(tp); 145 tp->t_iflag = TTYDEF_IFLAG; 146 tp->t_oflag = TTYDEF_OFLAG; 147 tp->t_cflag = TTYDEF_CFLAG; 148 tp->t_lflag = TTYDEF_LFLAG; 149 tp->t_ispeed = tp->t_ospeed = dcadefaultrate; 150 dcaparam(tp, &tp->t_termios); 151 ttsetwater(tp); 152 } else if (tp->t_state&TS_XCLUDE && u.u_uid != 0) 153 return (EBUSY); 154 (void) dcamctl(dev, MCR_DTR | MCR_RTS, DMSET); 155 if ((dcasoftCAR & (1 << unit)) || (dcamctl(dev, 0, DMGET) & MSR_DCD)) 156 tp->t_state |= TS_CARR_ON; 157 (void) spltty(); 158 while (!(flag&O_NONBLOCK) && !(tp->t_cflag&CLOCAL) && 159 (tp->t_state & TS_CARR_ON) == 0) { 160 tp->t_state |= TS_WOPEN; 161 sleep((caddr_t)&tp->t_rawq, TTIPRI); 162 } 163 (void) spl0(); 164 return ((*linesw[tp->t_line].l_open)(dev, tp)); 165 } 166 167 /*ARGSUSED*/ 168 dcaclose(dev, flag) 169 dev_t dev; 170 { 171 register struct tty *tp; 172 register struct dcadevice *dca; 173 register int unit; 174 175 unit = UNIT(dev); 176 dca = dca_addr[unit]; 177 tp = &dca_tty[unit]; 178 (*linesw[tp->t_line].l_close)(tp); 179 dca->dca_cfcr &= ~CFCR_SBREAK; 180 #ifdef KGDB 181 /* do not disable interrupts if debugging */ 182 if (kgdb_dev != makedev(1, unit)) 183 #endif 184 dca->dca_ier = 0; 185 if (tp->t_cflag&HUPCL || tp->t_state&TS_WOPEN || 186 (tp->t_state&TS_ISOPEN) == 0) 187 (void) dcamctl(dev, 0, DMSET); 188 ttyclose(tp); 189 return(0); 190 } 191 192 dcaread(dev, uio, flag) 193 dev_t dev; 194 struct uio *uio; 195 { 196 register struct tty *tp = &dca_tty[UNIT(dev)]; 197 198 return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 199 } 200 201 dcawrite(dev, uio, flag) 202 dev_t dev; 203 struct uio *uio; 204 { 205 int unit = UNIT(dev); 206 register struct tty *tp = &dca_tty[unit]; 207 208 if (unit == dcaconsole && constty && 209 (constty->t_state&(TS_CARR_ON|TS_ISOPEN))==(TS_CARR_ON|TS_ISOPEN)) 210 tp = constty; 211 return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 212 } 213 214 dcaintr(unit) 215 register int unit; 216 { 217 register struct dcadevice *dca; 218 register int code; 219 220 dca = dca_addr[unit]; 221 if ((dca->dca_ic & IC_IR) == 0) 222 return(0); 223 while (((code = dca->dca_iir) & IIR_NOPEND) == 0) { 224 code &= IIR_IMASK; 225 if (code == IIR_RLS) 226 dcaeint(unit, dca); 227 else if (code == IIR_RXRDY) 228 dcarint(unit, dca); 229 else if (code == IIR_TXRDY) 230 dcaxint(unit, dca); 231 else 232 dcamint(unit, dca); 233 } 234 return(1); 235 } 236 237 dcaeint(unit, dca) 238 register int unit; 239 register struct dcadevice *dca; 240 { 241 register struct tty *tp; 242 register int stat, c; 243 244 tp = &dca_tty[unit]; 245 stat = dca->dca_lsr; 246 c = dca->dca_data & 0xff; 247 if ((tp->t_state & TS_ISOPEN) == 0) { 248 #ifdef KGDB 249 /* we don't care about parity errors */ 250 if (((stat & (LSR_BI|LSR_FE|LSR_PE)) == LSR_PE) && 251 kgdb_dev == makedev(1, unit) && c == '!') { 252 printf("kgdb trap from dca%d\n", unit); 253 /* trap into kgdb */ 254 asm("trap #15;"); 255 } 256 #endif 257 return; 258 } 259 if (stat & (LSR_BI | LSR_FE)) 260 c |= TTY_FE; 261 else if (stat & LSR_PE) 262 c |= TTY_PE; 263 else if (stat & LSR_OE) 264 log(LOG_WARNING, "dca%d: silo overflow\n", unit); 265 (*linesw[tp->t_line].l_rint)(c, tp); 266 } 267 268 dcarint(unit, dca) 269 int unit; 270 register struct dcadevice *dca; 271 { 272 register struct tty *tp; 273 register int c; 274 275 tp = &dca_tty[unit]; 276 c = dca->dca_data; 277 if ((tp->t_state & TS_ISOPEN) == 0) { 278 #ifdef KGDB 279 if (kgdb_dev == makedev(1, unit) && c == '!') { 280 printf("kgdb trap from dca%d\n", unit); 281 /* trap into kgdb */ 282 asm("trap #15;"); 283 } 284 #endif 285 return; 286 } 287 (*linesw[tp->t_line].l_rint)(c, tp); 288 } 289 290 /*ARGSUSED*/ 291 dcaxint(unit, dca) 292 int unit; 293 struct dcadevice *dca; 294 { 295 register struct tty *tp; 296 297 tp = &dca_tty[unit]; 298 tp->t_state &= ~TS_BUSY; 299 if (tp->t_state & TS_FLUSH) 300 tp->t_state &= ~TS_FLUSH; 301 if (tp->t_line) 302 (*linesw[tp->t_line].l_start)(tp); 303 else 304 dcastart(tp); 305 } 306 307 dcamint(unit, dca) 308 register int unit; 309 register struct dcadevice *dca; 310 { 311 register struct tty *tp; 312 register int stat; 313 314 tp = &dca_tty[unit]; 315 stat = dca->dca_msr; 316 if ((stat & MSR_CCD) && (dcasoftCAR & (1 << unit)) == 0) { 317 if (stat & MSR_DCD) 318 (void) (*linesw[tp->t_line].l_modem)(tp, 1); 319 else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0) 320 dca->dca_mcr &= ~(MCR_DTR | MCR_RTS); 321 } 322 } 323 324 dcaioctl(dev, cmd, data, flag) 325 dev_t dev; 326 caddr_t data; 327 { 328 register struct tty *tp; 329 register int unit = UNIT(dev); 330 register struct dcadevice *dca; 331 register int error; 332 333 tp = &dca_tty[unit]; 334 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); 335 if (error >= 0) 336 return (error); 337 error = ttioctl(tp, cmd, data, flag); 338 if (error >= 0) 339 return (error); 340 341 dca = dca_addr[unit]; 342 switch (cmd) { 343 344 case TIOCSBRK: 345 dca->dca_cfcr |= CFCR_SBREAK; 346 break; 347 348 case TIOCCBRK: 349 dca->dca_cfcr &= ~CFCR_SBREAK; 350 break; 351 352 case TIOCSDTR: 353 (void) dcamctl(dev, MCR_DTR | MCR_RTS, DMBIS); 354 break; 355 356 case TIOCCDTR: 357 (void) dcamctl(dev, MCR_DTR | MCR_RTS, DMBIC); 358 break; 359 360 case TIOCMSET: 361 (void) dcamctl(dev, *(int *)data, DMSET); 362 break; 363 364 case TIOCMBIS: 365 (void) dcamctl(dev, *(int *)data, DMBIS); 366 break; 367 368 case TIOCMBIC: 369 (void) dcamctl(dev, *(int *)data, DMBIC); 370 break; 371 372 case TIOCMGET: 373 *(int *)data = dcamctl(dev, 0, DMGET); 374 break; 375 376 default: 377 return (ENOTTY); 378 } 379 return (0); 380 } 381 382 dcaparam(tp, t) 383 register struct tty *tp; 384 register struct termios *t; 385 { 386 register struct dcadevice *dca; 387 register int cfcr, cflag = t->c_cflag; 388 int unit = UNIT(tp->t_dev); 389 int ospeed = ttspeedtab(t->c_ospeed, dcaspeedtab); 390 391 /* check requested parameters */ 392 if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed)) 393 return(EINVAL); 394 /* and copy to tty */ 395 tp->t_ispeed = t->c_ispeed; 396 tp->t_ospeed = t->c_ospeed; 397 tp->t_cflag = cflag; 398 399 dca = dca_addr[unit]; 400 dca->dca_ier = IER_ERXRDY | IER_ETXRDY | IER_ERLS | IER_EMSC; 401 if (ospeed == 0) { 402 (void) dcamctl(unit, 0, DMSET); /* hang up line */ 403 return(0); 404 } 405 dca->dca_cfcr |= CFCR_DLAB; 406 dca->dca_data = ospeed & 0xFF; 407 dca->dca_ier = ospeed >> 8; 408 switch (cflag&CSIZE) { 409 case CS5: 410 cfcr = CFCR_5BITS; break; 411 case CS6: 412 cfcr = CFCR_6BITS; break; 413 case CS7: 414 cfcr = CFCR_7BITS; break; 415 case CS8: 416 cfcr = CFCR_8BITS; break; 417 } 418 if (cflag&PARENB) { 419 cfcr |= CFCR_PENAB; 420 if ((cflag&PARODD) == 0) 421 cfcr |= CFCR_PEVEN; 422 } 423 if (cflag&CSTOPB) 424 cfcr |= CFCR_STOPB; 425 dca->dca_cfcr = cfcr; 426 return(0); 427 } 428 429 dcastart(tp) 430 register struct tty *tp; 431 { 432 register struct dcadevice *dca; 433 int s, unit, c; 434 435 unit = UNIT(tp->t_dev); 436 dca = dca_addr[unit]; 437 s = spltty(); 438 if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) 439 goto out; 440 if (tp->t_outq.c_cc <= tp->t_lowat) { 441 if (tp->t_state&TS_ASLEEP) { 442 tp->t_state &= ~TS_ASLEEP; 443 wakeup((caddr_t)&tp->t_outq); 444 } 445 if (tp->t_wsel) { 446 selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); 447 tp->t_wsel = 0; 448 tp->t_state &= ~TS_WCOLL; 449 } 450 } 451 if (tp->t_outq.c_cc == 0) 452 goto out; 453 c = getc(&tp->t_outq); 454 tp->t_state |= TS_BUSY; 455 dca->dca_data = c; 456 out: 457 splx(s); 458 } 459 460 /* 461 * Stop output on a line. 462 */ 463 /*ARGSUSED*/ 464 dcastop(tp, flag) 465 register struct tty *tp; 466 { 467 register int s; 468 469 s = spltty(); 470 if (tp->t_state & TS_BUSY) { 471 if ((tp->t_state&TS_TTSTOP)==0) 472 tp->t_state |= TS_FLUSH; 473 } 474 splx(s); 475 } 476 477 dcamctl(dev, bits, how) 478 dev_t dev; 479 int bits, how; 480 { 481 register struct dcadevice *dca; 482 register int unit; 483 int s; 484 485 unit = UNIT(dev); 486 dca = dca_addr[unit]; 487 s = spltty(); 488 switch (how) { 489 490 case DMSET: 491 dca->dca_mcr = bits; 492 break; 493 494 case DMBIS: 495 dca->dca_mcr |= bits; 496 break; 497 498 case DMBIC: 499 dca->dca_mcr &= ~bits; 500 break; 501 502 case DMGET: 503 bits = dca->dca_msr; 504 break; 505 } 506 (void) splx(s); 507 return(bits); 508 } 509 510 /* 511 * Following are all routines needed for DCA to act as console 512 */ 513 #include "machine/cons.h" 514 515 dcacnprobe(cp) 516 struct consdev *cp; 517 { 518 int unit, i; 519 extern int dcaopen(); 520 521 /* XXX: ick */ 522 unit = CONUNIT; 523 dca_addr[CONUNIT] = CONADDR; 524 525 /* make sure hardware exists */ 526 if (badaddr((short *)dca_addr[unit])) { 527 cp->cn_pri = CN_DEAD; 528 return; 529 } 530 531 /* locate the major number */ 532 for (i = 0; i < nchrdev; i++) 533 if (cdevsw[i].d_open == dcaopen) 534 break; 535 536 /* initialize required fields */ 537 cp->cn_dev = makedev(i, unit); 538 cp->cn_tp = &dca_tty[unit]; 539 switch (dca_addr[unit]->dca_irid) { 540 case DCAID0: 541 case DCAID1: 542 cp->cn_pri = CN_NORMAL; 543 break; 544 case DCAREMID0: 545 case DCAREMID1: 546 cp->cn_pri = CN_REMOTE; 547 break; 548 default: 549 cp->cn_pri = CN_DEAD; 550 break; 551 } 552 } 553 554 dcacninit(cp) 555 struct consdev *cp; 556 { 557 int unit = UNIT(cp->cn_dev); 558 559 dcainit(unit); 560 dcaconsole = unit; 561 } 562 563 dcainit(unit) 564 int unit; 565 { 566 register struct dcadevice *dca; 567 int s, rate; 568 short stat; 569 570 #ifdef lint 571 stat = unit; if (stat) return; 572 #endif 573 dca = dca_addr[unit]; 574 s = splhigh(); 575 dca->dca_irid = 0xFF; 576 DELAY(100); 577 dca->dca_ic = IC_IE; 578 dca->dca_cfcr = CFCR_DLAB; 579 rate = ttspeedtab(dcadefaultrate, dcaspeedtab); 580 dca->dca_data = rate & 0xFF; 581 dca->dca_ier = rate >> 8; 582 dca->dca_cfcr = CFCR_8BITS; 583 dca->dca_ier = IER_ERXRDY | IER_ETXRDY; 584 stat = dca->dca_iir; 585 splx(s); 586 } 587 588 dcacngetc(dev) 589 { 590 register struct dcadevice *dca = dca_addr[UNIT(dev)]; 591 short stat; 592 int c, s; 593 594 #ifdef lint 595 stat = dev; if (stat) return(0); 596 #endif 597 s = splhigh(); 598 while (((stat = dca->dca_lsr) & LSR_RXRDY) == 0) 599 ; 600 c = dca->dca_data; 601 stat = dca->dca_iir; 602 splx(s); 603 return(c); 604 } 605 606 /* 607 * Console kernel output character routine. 608 */ 609 dcacnputc(dev, c) 610 dev_t dev; 611 register int c; 612 { 613 register struct dcadevice *dca = dca_addr[UNIT(dev)]; 614 register int timo; 615 short stat; 616 int s = splhigh(); 617 618 #ifdef lint 619 stat = dev; if (stat) return; 620 #endif 621 if (dcaconsole == -1) { 622 (void) dcainit(UNIT(dev)); 623 dcaconsole = UNIT(dev); 624 } 625 /* wait for any pending transmission to finish */ 626 timo = 50000; 627 while (((stat = dca->dca_lsr) & LSR_TXRDY) == 0 && --timo) 628 ; 629 dca->dca_data = c; 630 /* wait for this transmission to complete */ 631 timo = 1500000; 632 while (((stat = dca->dca_lsr) & LSR_TXRDY) == 0 && --timo) 633 ; 634 /* clear any interrupts generated by this transmission */ 635 stat = dca->dca_iir; 636 splx(s); 637 } 638 #endif 639