1 /* 2 * Copyright (c) 1982, 1986 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 * 6 * @(#)dmx.c 7.2 (Berkeley) 04/12/90 7 */ 8 9 /* 10 * Common code for DMF32 and DMZ32 drivers 11 */ 12 #include "dmf.h" 13 #include "dmz.h" 14 #if NDMF + NDMZ > 0 15 16 #include "machine/pte.h" 17 18 #include "uba.h" 19 #include "param.h" 20 #include "conf.h" 21 #include "user.h" 22 #include "proc.h" 23 #include "ioctl.h" 24 #include "tty.h" 25 #include "map.h" 26 #include "buf.h" 27 #include "vm.h" 28 #include "bkmac.h" 29 #include "clist.h" 30 #include "file.h" 31 #include "uio.h" 32 #include "kernel.h" 33 #include "syslog.h" 34 35 #include "dmx.h" 36 #include "ubareg.h" 37 #include "ubavar.h" 38 #include "dmxreg.h" 39 #include "dmreg.h" 40 41 #ifndef PORTSELECTOR 42 #define ISPEED TTYDEF_SPEED 43 #define LFLAG TTYDEF_LFLAG 44 #else 45 #define ISPEED B4800 46 #define IFLAGS (TTYDEF_LFLAG&~ECHO) 47 #endif 48 49 #ifndef DMX_TIMEOUT 50 #define DMX_TIMEOUT 10 51 #endif 52 int dmx_timeout = DMX_TIMEOUT; /* silo timeout, in ms */ 53 int dmx_mindma = 4; /* don't dma below this point */ 54 55 struct speedtab dmxspeedtab[] = { 56 0, 0, 57 75, 1, 58 110, 2, 59 134, 3, 60 150, 4, 61 300, 5, 62 600, 6, 63 1200, 7, 64 1800, 010, 65 2400, 012, 66 4800, 014, 67 9600, 016, 68 19200, 017, 69 EXTA, 017, 70 -1, -1 71 }; 72 /* 73 * The clist space is mapped by the drivers onto each UNIBUS. 74 * The UBACVT macro converts a clist space address for unibus uban 75 * into an I/O space address for the DMA routine. 76 */ 77 int cbase[NUBA]; /* base address in unibus map */ 78 #define UBACVT(x, uban) (cbase[uban] + ((x)-(char *)cfree)) 79 80 int ttrstrt(); 81 82 /* 83 * DMF/DMZ open common code 84 */ 85 dmxopen(tp, sc, flag) 86 register struct tty *tp; 87 register struct dmx_softc *sc; 88 { 89 int s, unit, error = 0; 90 int dmxparam(); 91 92 s = spltty(); 93 if ((sc->dmx_flags & DMX_ACTIVE) == 0) { 94 sc->dmx_octet->csr |= DMF_IE; 95 sc->dmx_flags |= DMX_ACTIVE; 96 sc->dmx_octet->rsp = dmx_timeout; 97 } 98 splx(s); 99 if (tp->t_state & TS_XCLUDE && u.u_uid != 0) 100 return (EBUSY); 101 /* 102 * If this is first open, initialize tty state to default. 103 */ 104 if ((tp->t_state&TS_ISOPEN) == 0) { 105 ttychars(tp); 106 #ifndef PORTSELECTOR 107 if (tp->t_ispeed == 0) { 108 #endif 109 tp->t_iflag = TTYDEF_IFLAG; 110 tp->t_oflag = TTYDEF_OFLAG; 111 tp->t_cflag = TTYDEF_CFLAG; 112 tp->t_lflag = LFLAG; 113 tp->t_ispeed = tp->t_ospeed = ISPEED; 114 #ifdef PORTSELECTOR 115 tp->t_cflag |= HUPCL; 116 #else 117 } 118 #endif 119 } 120 dmxparam(tp, &tp->t_termios); 121 122 unit = minor(tp->t_dev) & 07; 123 /* 124 * Wait for carrier, then process line discipline specific open. 125 */ 126 s = spltty(); 127 for (;;) { 128 if ((dmxmctl(tp, DMF_ON, DMSET) & DMF_CAR) || 129 (sc->dmx_softCAR & (1 << unit))) 130 tp->t_state |= TS_CARR_ON; 131 if (tp->t_state&TS_CARR_ON || flag&O_NONBLOCK || 132 tp->t_cflag&CLOCAL) 133 break; 134 tp->t_state |= TS_WOPEN; 135 if (error = tsleep((caddr_t)&tp->t_rawq, TTIPRI | PCATCH, 136 ttopen, 0)) 137 break; 138 } 139 splx(s); 140 if (error) 141 return (error); 142 return ((*linesw[tp->t_line].l_open)(tp->t_dev, tp)); 143 } 144 145 dmxclose(tp) 146 register struct tty *tp; 147 { 148 149 (*linesw[tp->t_line].l_close)(tp); 150 (void) dmxmctl(tp, DMF_BRK, DMBIC); 151 if (tp->t_cflag & HUPCL || (tp->t_state & TS_ISOPEN) == 0) 152 (void) dmxmctl(tp, DMF_OFF, DMSET); 153 return (ttyclose(tp)); 154 } 155 156 dmxrint(sc) 157 register struct dmx_softc *sc; 158 { 159 register c, cc; 160 register struct tty *tp; 161 register struct dmx_octet *addr; 162 int unit; 163 int overrun = 0; 164 165 addr = (struct dmx_octet *)sc->dmx_octet; 166 /* 167 * Loop fetching characters from the silo for this 168 * octet until there are no more in the silo. 169 */ 170 while ((c = addr->rbuf) < 0) { 171 cc = c&0xff; 172 unit = (c >> 8) & 07; 173 tp = sc->dmx_tty + unit; 174 if (c & DMF_DSC) { 175 addr->csr = DMF_IE | DMFIR_RMSTSC | unit; 176 if (addr->rmstsc & DMF_CAR) 177 (void)(*linesw[tp->t_line].l_modem)(tp, 1); 178 else if ((sc->dmx_softCAR & (1 << unit)) == 0 && 179 (*linesw[tp->t_line].l_modem)(tp, 0) == 0) { 180 addr->csr = DMF_IE | DMFIR_LCR | unit; 181 addr->lctms = DMF_ENA; 182 } 183 continue; 184 } 185 if ((tp->t_state&TS_ISOPEN) == 0) { 186 wakeup((caddr_t)&tp->t_rawq); 187 #ifdef PORTSELECTOR 188 if ((tp->t_state & TS_WOPEN) == 0) 189 #endif 190 continue; 191 } 192 if (c & (DMF_PE|DMF_DO|DMF_FE)) { 193 if (c & DMF_PE) 194 cc |= TTY_PE; 195 if ((c & DMF_DO) && overrun == 0) { 196 log(LOG_WARNING, 197 "dm%c%d: silo overflow, line %d\n", 198 sc->dmx_type, sc->dmx_unit, 199 sc->dmx_unit0 + unit); 200 overrun = 1; 201 } 202 if (c & DMF_FE) 203 cc |= TTY_FE; 204 } 205 (*linesw[tp->t_line].l_rint)(cc, tp); 206 } 207 } 208 209 dmxioctl(tp, cmd, data, flag) 210 register struct tty *tp; 211 caddr_t data; 212 { 213 int error; 214 215 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); 216 if (error >= 0) 217 return (error); 218 error = ttioctl(tp, cmd, data, flag); 219 if (error >= 0) 220 return (error); 221 222 switch (cmd) { 223 224 case TIOCSBRK: 225 (void) dmxmctl(tp, DMF_BRK, DMBIS); 226 break; 227 228 case TIOCCBRK: 229 (void) dmxmctl(tp, DMF_BRK, DMBIC); 230 break; 231 232 case TIOCSDTR: 233 (void) dmxmctl(tp, DMF_DTR|DMF_RTS, DMBIS); 234 break; 235 236 case TIOCCDTR: 237 (void) dmxmctl(tp, DMF_DTR|DMF_RTS, DMBIC); 238 break; 239 240 case TIOCMSET: 241 (void) dmxmctl(tp, dmtodmx(*(int *)data), DMSET); 242 break; 243 244 case TIOCMBIS: 245 (void) dmxmctl(tp, dmtodmx(*(int *)data), DMBIS); 246 break; 247 248 case TIOCMBIC: 249 (void) dmxmctl(tp, dmtodmx(*(int *)data), DMBIC); 250 break; 251 252 case TIOCMGET: 253 *(int *)data = dmxmctl(tp, 0, DMGET); 254 break; 255 256 default: 257 return (ENOTTY); 258 } 259 return (0); 260 } 261 262 /* 263 * modem control 264 * "bits" are dmf/dmz lcr format; 265 * return of DMGET is DM11 format. 266 */ 267 dmxmctl(tp, bits, how) 268 struct tty *tp; 269 int bits, how; 270 { 271 register struct dmx_octet *addr; 272 register int unit, mbits, lcr; 273 int s; 274 275 unit = minor(tp->t_dev) & 07; 276 addr = (struct dmx_octet *)(tp->t_addr); 277 278 s = spltty(); 279 addr->csr = DMF_IE | DMFIR_RMSTSC | unit; 280 mbits = addr->rmstsc & 0xff00; 281 addr->csr = DMF_IE | DMFIR_LCR | unit; 282 lcr = addr->lctms; 283 284 switch (how) { 285 case DMSET: 286 lcr = bits; 287 break; 288 289 case DMBIS: 290 lcr |= bits; 291 break; 292 293 case DMBIC: 294 lcr &= ~bits; 295 break; 296 297 case DMGET: 298 splx(s); 299 return (dmxtodm(mbits, lcr)); 300 } 301 addr->lctms = lcr; 302 (void) splx(s); 303 return (mbits); 304 } 305 306 /* 307 * Routine to convert modem status from dm to dmf/dmz lctmr format. 308 */ 309 dmtodmx(bits) 310 register int bits; 311 { 312 register int lcr = DMF_ENA; 313 314 if (bits & DML_DTR) 315 lcr |= DMF_DTR; 316 if (bits & DML_RTS) 317 lcr |= DMF_RTS; 318 if (bits & DML_ST) 319 lcr |= DMF_SRTS; 320 if (bits & DML_USR) 321 lcr |= DMF_USRW; 322 return (lcr); 323 } 324 325 /* 326 * Routine to convert modem status from dmf/dmz receive modem status 327 * and line control register to dm format. 328 * If dmf/dmz user modem read bit set, set DML_USR. 329 */ 330 dmxtodm(mstat, lcr) 331 register int mstat, lcr; 332 { 333 334 mstat = ((mstat & (DMF_DSR|DMF_RNG|DMF_CAR|DMF_CTS|DMF_SR)) >> 7) | 335 ((mstat & DMF_USRR) >> 1) | DML_LE; 336 if (lcr & DMF_DTR) 337 mstat |= DML_DTR; 338 if (lcr & DMF_SRTS) 339 mstat |= DML_ST; 340 if (lcr & DMF_RTS) 341 mstat |= DML_RTS; 342 return (mstat); 343 } 344 345 346 /* 347 * Set parameters from open or ioctl into the hardware registers. 348 */ 349 dmxparam(tp, t) 350 register struct tty *tp; 351 register struct termios *t; 352 { 353 register struct dmx_octet *addr; 354 register int lpar, lcr; 355 register int cflag = t->c_cflag; 356 int s, unit; 357 int ispeed = ttspeedtab(t->c_ispeed, dmxspeedtab); 358 int ospeed = ttspeedtab(t->c_ospeed, dmxspeedtab); 359 360 /* check requested parameters */ 361 if (ospeed < 0 || ispeed < 0 || (cflag&CSIZE) == CS5) 362 return(EINVAL); 363 if (ispeed == 0) 364 ispeed = ospeed; 365 /* and copy to tty */ 366 tp->t_ispeed = t->c_ispeed; 367 tp->t_ospeed = t->c_ospeed; 368 tp->t_cflag = cflag; 369 370 addr = (struct dmx_octet *)tp->t_addr; 371 unit = minor(tp->t_dev) & 07; 372 /* 373 * Block interrupts so parameters will be set 374 * before the line interrupts. 375 */ 376 s = spltty(); 377 addr->csr = unit | DMFIR_LCR | DMF_IE; 378 if (ospeed == 0) { 379 tp->t_cflag |= HUPCL; 380 (void) dmxmctl(tp, DMF_OFF, DMSET); 381 splx(s); 382 return; 383 } 384 lpar = (ospeed<<12) | (ispeed<<8); 385 lcr = DMF_ENA; 386 switch (cflag&CSIZE) { 387 case CS6: lpar |= BITS6; break; 388 case CS7: lpar |= BITS7; break; 389 case CS8: lpar |= BITS8; break; 390 } 391 if (cflag&PARENB) 392 lpar |= PENABLE; 393 if (!(cflag&PARODD)) 394 lpar |= EPAR; 395 if (cflag&CSTOPB) 396 lpar |= TWOSB; 397 398 lpar |= (unit&07); 399 addr->lpr = lpar; 400 addr->lctms = (addr->lctms &~ 0xff) | lcr; 401 splx(s); 402 return 0; 403 } 404 405 /* 406 * Process a transmit interrupt on an octet. 407 */ 408 dmxxint(sc) 409 register struct dmx_softc *sc; 410 { 411 register struct tty *tp; 412 register struct dmx_octet *addr; 413 register int t; 414 415 addr = (struct dmx_octet *)sc->dmx_octet; 416 while ((t = addr->csr) & DMF_TI) { 417 if (t & DMF_NXM) 418 /* SHOULD RESTART OR SOMETHING... */ 419 printf("dm%c%d: NXM line %d\n", sc->dmx_type, 420 sc->dmx_unit, sc->dmx_unit0 + (t >> 8 & 7)); 421 t = t >> 8 & 7; 422 tp = sc->dmx_tty + t; 423 tp->t_state &= ~TS_BUSY; 424 if (tp->t_state & TS_FLUSH) 425 tp->t_state &= ~TS_FLUSH; 426 #define new 427 #ifndef new 428 else if (sc->dmx_dmacount[t]) { 429 short cntr; 430 431 /* 432 * Do arithmetic in a short to make up 433 * for lost 16&17 bits. 434 */ 435 addr->csr = DMFIR_TBA | DMF_IE | t; 436 cntr = addr->tba - 437 UBACVT(tp->t_outq.c_cf, sc->dmx_ubanum); 438 ndflush(&tp->t_outq, (int)cntr); 439 } 440 #else 441 else if (sc->dmx_dmacount[t]) 442 ndflush(&tp->t_outq, sc->dmx_dmacount[t]); 443 sc->dmx_dmacount[t] = 0; 444 #endif 445 (*linesw[tp->t_line].l_start)(tp); 446 } 447 } 448 449 dmxstart(tp, sc) 450 register struct tty *tp; 451 struct dmx_softc *sc; 452 { 453 register struct dmx_octet *addr; 454 register int unit, nch; 455 int s; 456 457 unit = minor(tp->t_dev) & 07; 458 addr = (struct dmx_octet *)tp->t_addr; 459 460 /* 461 * Must hold interrupts in following code to prevent 462 * state of the tp from changing. 463 */ 464 s = spltty(); 465 /* 466 * If it's currently active, or delaying, no need to do anything. 467 */ 468 if (tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) 469 goto out; 470 /* 471 * If there are still characters to dma or in the silo, 472 * just reenable the transmitter. 473 */ 474 addr->csr = DMF_IE | DMFIR_TBUF | unit; 475 #ifdef new 476 if (addr->tsc || sc->dmx_dmacount[unit]) { 477 #else 478 if (addr->tsc) { 479 #endif 480 addr->csr = DMF_IE | DMFIR_LCR | unit; 481 addr->lctms = addr->lctms | DMF_TE; 482 tp->t_state |= TS_BUSY; 483 goto out; 484 } 485 /* 486 * If there are sleepers, and output has drained below low 487 * water mark, wake up the sleepers. 488 */ 489 if (tp->t_outq.c_cc <= tp->t_lowat) { 490 if (tp->t_state & TS_ASLEEP) { 491 tp->t_state &= ~TS_ASLEEP; 492 wakeup((caddr_t)&tp->t_outq); 493 } 494 if (tp->t_wsel) { 495 selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); 496 tp->t_wsel = 0; 497 tp->t_state &= ~TS_WCOLL; 498 } 499 } 500 /* 501 * Now restart transmission unless the output queue is 502 * empty. 503 */ 504 if (tp->t_outq.c_cc == 0) 505 goto out; 506 if (1 || !(tp->t_oflag&OPOST)) /*XXX*/ 507 nch = ndqb(&tp->t_outq, 0); 508 else { 509 if ((nch = ndqb(&tp->t_outq, 0200)) == 0) { 510 /* 511 * If first thing on queue is a delay process it. 512 */ 513 nch = getc(&tp->t_outq); 514 timeout(ttrstrt, (caddr_t)tp, (nch&0x7f)+6); 515 tp->t_state |= TS_TIMEOUT; 516 goto out; 517 } 518 } 519 /* 520 * If characters to transmit, restart transmission. 521 */ 522 if (nch >= dmx_mindma) { 523 register car; 524 525 sc->dmx_dmacount[unit] = nch; 526 addr->csr = DMF_IE | DMFIR_LCR | unit; 527 addr->lctms = addr->lctms | DMF_TE; 528 car = UBACVT(tp->t_outq.c_cf, sc->dmx_ubanum); 529 addr->csr = DMF_IE | DMFIR_TBA | unit; 530 addr->tba = car; 531 addr->tcc = ((car >> 2) & 0xc000) | nch; 532 tp->t_state |= TS_BUSY; 533 } else if (nch) { 534 register char *cp = tp->t_outq.c_cf; 535 register int i; 536 537 #ifndef new 538 sc->dmx_dmacount[unit] = 0; 539 #endif 540 nch = MIN(nch, DMF_SILOCNT); 541 addr->csr = DMF_IE | DMFIR_LCR | unit; 542 addr->lctms = addr->lctms | DMF_TE; 543 addr->csr = DMF_IE | DMFIR_TBUF | unit; 544 for (i = 0; i < nch; i++) 545 addr->tbuf = *cp++; 546 ndflush(&tp->t_outq, nch); 547 tp->t_state |= TS_BUSY; 548 } 549 out: 550 splx(s); 551 } 552 553 dmxstop(tp, sc, flag) 554 register struct tty *tp; 555 struct dmx_softc *sc; 556 { 557 register struct dmx_octet *addr; 558 register unit = minor(tp->t_dev) & 7; 559 int s; 560 561 addr = (struct dmx_octet *)tp->t_addr; 562 /* 563 * Block input/output interrupts while messing with state. 564 */ 565 s = spltty(); 566 if (flag) { 567 addr->csr = DMF_IE | DMFIR_TBUF | unit; 568 if (addr->tsc) { 569 /* 570 * Flush regardless of whether we're transmitting 571 * (TS_BUSY), if the silo contains untransmitted 572 * characters. 573 */ 574 addr->csr = DMFIR_LCR | unit | DMF_IE; 575 addr->lctms = addr->lctms | DMF_TE | DMF_FLUSH; 576 /* this will interrupt so let dmxxint handle the rest */ 577 tp->t_state |= TS_FLUSH|TS_BUSY; 578 } 579 /*#ifdef new*/ 580 sc->dmx_dmacount[unit] = 0; 581 /*#endif*/ 582 } else { 583 /* 584 * Stop transmission by disabling 585 * the transmitter. We'll pick up where we 586 * left off by reenabling in dmxstart. 587 */ 588 addr->csr = DMFIR_LCR | unit | DMF_IE; 589 addr->lctms = addr->lctms &~ DMF_TE; 590 /* no interrupt here */ 591 tp->t_state &= ~TS_BUSY; 592 } 593 splx(s); 594 } 595 #endif NDMF + NDMZ 596