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.3 (Berkeley) 06/06/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 (error = ttclosed(tp))) 138 break; 139 } 140 splx(s); 141 if (error) 142 return (error); 143 return ((*linesw[tp->t_line].l_open)(tp->t_dev, tp)); 144 } 145 146 dmxclose(tp) 147 register struct tty *tp; 148 { 149 150 (*linesw[tp->t_line].l_close)(tp); 151 (void) dmxmctl(tp, DMF_BRK, DMBIC); 152 if (tp->t_cflag & HUPCL || (tp->t_state & TS_ISOPEN) == 0) 153 (void) dmxmctl(tp, DMF_OFF, DMSET); 154 return (ttyclose(tp)); 155 } 156 157 dmxrint(sc) 158 register struct dmx_softc *sc; 159 { 160 register c, cc; 161 register struct tty *tp; 162 register struct dmx_octet *addr; 163 int unit; 164 int overrun = 0; 165 166 addr = (struct dmx_octet *)sc->dmx_octet; 167 /* 168 * Loop fetching characters from the silo for this 169 * octet until there are no more in the silo. 170 */ 171 while ((c = addr->rbuf) < 0) { 172 cc = c&0xff; 173 unit = (c >> 8) & 07; 174 tp = sc->dmx_tty + unit; 175 if (c & DMF_DSC) { 176 addr->csr = DMF_IE | DMFIR_RMSTSC | unit; 177 if (addr->rmstsc & DMF_CAR) 178 (void)(*linesw[tp->t_line].l_modem)(tp, 1); 179 else if ((sc->dmx_softCAR & (1 << unit)) == 0 && 180 (*linesw[tp->t_line].l_modem)(tp, 0) == 0) { 181 addr->csr = DMF_IE | DMFIR_LCR | unit; 182 addr->lctms = DMF_ENA; 183 } 184 continue; 185 } 186 if ((tp->t_state&TS_ISOPEN) == 0) { 187 wakeup((caddr_t)&tp->t_rawq); 188 #ifdef PORTSELECTOR 189 if ((tp->t_state & TS_WOPEN) == 0) 190 #endif 191 continue; 192 } 193 if (c & (DMF_PE|DMF_DO|DMF_FE)) { 194 if (c & DMF_PE) 195 cc |= TTY_PE; 196 if ((c & DMF_DO) && overrun == 0) { 197 log(LOG_WARNING, 198 "dm%c%d: silo overflow, line %d\n", 199 sc->dmx_type, sc->dmx_unit, 200 sc->dmx_unit0 + unit); 201 overrun = 1; 202 } 203 if (c & DMF_FE) 204 cc |= TTY_FE; 205 } 206 (*linesw[tp->t_line].l_rint)(cc, tp); 207 } 208 } 209 210 dmxioctl(tp, cmd, data, flag) 211 register struct tty *tp; 212 caddr_t data; 213 { 214 int error; 215 216 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); 217 if (error >= 0) 218 return (error); 219 error = ttioctl(tp, cmd, data, flag); 220 if (error >= 0) 221 return (error); 222 223 switch (cmd) { 224 225 case TIOCSBRK: 226 (void) dmxmctl(tp, DMF_BRK, DMBIS); 227 break; 228 229 case TIOCCBRK: 230 (void) dmxmctl(tp, DMF_BRK, DMBIC); 231 break; 232 233 case TIOCSDTR: 234 (void) dmxmctl(tp, DMF_DTR|DMF_RTS, DMBIS); 235 break; 236 237 case TIOCCDTR: 238 (void) dmxmctl(tp, DMF_DTR|DMF_RTS, DMBIC); 239 break; 240 241 case TIOCMSET: 242 (void) dmxmctl(tp, dmtodmx(*(int *)data), DMSET); 243 break; 244 245 case TIOCMBIS: 246 (void) dmxmctl(tp, dmtodmx(*(int *)data), DMBIS); 247 break; 248 249 case TIOCMBIC: 250 (void) dmxmctl(tp, dmtodmx(*(int *)data), DMBIC); 251 break; 252 253 case TIOCMGET: 254 *(int *)data = dmxmctl(tp, 0, DMGET); 255 break; 256 257 default: 258 return (ENOTTY); 259 } 260 return (0); 261 } 262 263 /* 264 * modem control 265 * "bits" are dmf/dmz lcr format; 266 * return of DMGET is DM11 format. 267 */ 268 dmxmctl(tp, bits, how) 269 struct tty *tp; 270 int bits, how; 271 { 272 register struct dmx_octet *addr; 273 register int unit, mbits, lcr; 274 int s; 275 276 unit = minor(tp->t_dev) & 07; 277 addr = (struct dmx_octet *)(tp->t_addr); 278 279 s = spltty(); 280 addr->csr = DMF_IE | DMFIR_RMSTSC | unit; 281 mbits = addr->rmstsc & 0xff00; 282 addr->csr = DMF_IE | DMFIR_LCR | unit; 283 lcr = addr->lctms; 284 285 switch (how) { 286 case DMSET: 287 lcr = bits; 288 break; 289 290 case DMBIS: 291 lcr |= bits; 292 break; 293 294 case DMBIC: 295 lcr &= ~bits; 296 break; 297 298 case DMGET: 299 splx(s); 300 return (dmxtodm(mbits, lcr)); 301 } 302 addr->lctms = lcr; 303 (void) splx(s); 304 return (mbits); 305 } 306 307 /* 308 * Routine to convert modem status from dm to dmf/dmz lctmr format. 309 */ 310 dmtodmx(bits) 311 register int bits; 312 { 313 register int lcr = DMF_ENA; 314 315 if (bits & DML_DTR) 316 lcr |= DMF_DTR; 317 if (bits & DML_RTS) 318 lcr |= DMF_RTS; 319 if (bits & DML_ST) 320 lcr |= DMF_SRTS; 321 if (bits & DML_USR) 322 lcr |= DMF_USRW; 323 return (lcr); 324 } 325 326 /* 327 * Routine to convert modem status from dmf/dmz receive modem status 328 * and line control register to dm format. 329 * If dmf/dmz user modem read bit set, set DML_USR. 330 */ 331 dmxtodm(mstat, lcr) 332 register int mstat, lcr; 333 { 334 335 mstat = ((mstat & (DMF_DSR|DMF_RNG|DMF_CAR|DMF_CTS|DMF_SR)) >> 7) | 336 ((mstat & DMF_USRR) >> 1) | DML_LE; 337 if (lcr & DMF_DTR) 338 mstat |= DML_DTR; 339 if (lcr & DMF_SRTS) 340 mstat |= DML_ST; 341 if (lcr & DMF_RTS) 342 mstat |= DML_RTS; 343 return (mstat); 344 } 345 346 347 /* 348 * Set parameters from open or ioctl into the hardware registers. 349 */ 350 dmxparam(tp, t) 351 register struct tty *tp; 352 register struct termios *t; 353 { 354 register struct dmx_octet *addr; 355 register int lpar, lcr; 356 register int cflag = t->c_cflag; 357 int s, unit; 358 int ispeed = ttspeedtab(t->c_ispeed, dmxspeedtab); 359 int ospeed = ttspeedtab(t->c_ospeed, dmxspeedtab); 360 361 /* check requested parameters */ 362 if (ospeed < 0 || ispeed < 0 || (cflag&CSIZE) == CS5) 363 return(EINVAL); 364 if (ispeed == 0) 365 ispeed = ospeed; 366 /* and copy to tty */ 367 tp->t_ispeed = t->c_ispeed; 368 tp->t_ospeed = t->c_ospeed; 369 tp->t_cflag = cflag; 370 371 addr = (struct dmx_octet *)tp->t_addr; 372 unit = minor(tp->t_dev) & 07; 373 /* 374 * Block interrupts so parameters will be set 375 * before the line interrupts. 376 */ 377 s = spltty(); 378 addr->csr = unit | DMFIR_LCR | DMF_IE; 379 if (ospeed == 0) { 380 tp->t_cflag |= HUPCL; 381 (void) dmxmctl(tp, DMF_OFF, DMSET); 382 splx(s); 383 return; 384 } 385 lpar = (ospeed<<12) | (ispeed<<8); 386 lcr = DMF_ENA; 387 switch (cflag&CSIZE) { 388 case CS6: lpar |= BITS6; break; 389 case CS7: lpar |= BITS7; break; 390 case CS8: lpar |= BITS8; break; 391 } 392 if (cflag&PARENB) 393 lpar |= PENABLE; 394 if (!(cflag&PARODD)) 395 lpar |= EPAR; 396 if (cflag&CSTOPB) 397 lpar |= TWOSB; 398 399 lpar |= (unit&07); 400 addr->lpr = lpar; 401 addr->lctms = (addr->lctms &~ 0xff) | lcr; 402 splx(s); 403 return 0; 404 } 405 406 /* 407 * Process a transmit interrupt on an octet. 408 */ 409 dmxxint(sc) 410 register struct dmx_softc *sc; 411 { 412 register struct tty *tp; 413 register struct dmx_octet *addr; 414 register int t; 415 416 addr = (struct dmx_octet *)sc->dmx_octet; 417 while ((t = addr->csr) & DMF_TI) { 418 if (t & DMF_NXM) 419 /* SHOULD RESTART OR SOMETHING... */ 420 printf("dm%c%d: NXM line %d\n", sc->dmx_type, 421 sc->dmx_unit, sc->dmx_unit0 + (t >> 8 & 7)); 422 t = t >> 8 & 7; 423 tp = sc->dmx_tty + t; 424 tp->t_state &= ~TS_BUSY; 425 if (tp->t_state & TS_FLUSH) 426 tp->t_state &= ~TS_FLUSH; 427 #define new 428 #ifndef new 429 else if (sc->dmx_dmacount[t]) { 430 short cntr; 431 432 /* 433 * Do arithmetic in a short to make up 434 * for lost 16&17 bits. 435 */ 436 addr->csr = DMFIR_TBA | DMF_IE | t; 437 cntr = addr->tba - 438 UBACVT(tp->t_outq.c_cf, sc->dmx_ubanum); 439 ndflush(&tp->t_outq, (int)cntr); 440 } 441 #else 442 else if (sc->dmx_dmacount[t]) 443 ndflush(&tp->t_outq, sc->dmx_dmacount[t]); 444 sc->dmx_dmacount[t] = 0; 445 #endif 446 (*linesw[tp->t_line].l_start)(tp); 447 } 448 } 449 450 dmxstart(tp, sc) 451 register struct tty *tp; 452 struct dmx_softc *sc; 453 { 454 register struct dmx_octet *addr; 455 register int unit, nch; 456 int s; 457 458 unit = minor(tp->t_dev) & 07; 459 addr = (struct dmx_octet *)tp->t_addr; 460 461 /* 462 * Must hold interrupts in following code to prevent 463 * state of the tp from changing. 464 */ 465 s = spltty(); 466 /* 467 * If it's currently active, or delaying, no need to do anything. 468 */ 469 if (tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) 470 goto out; 471 /* 472 * If there are still characters to dma or in the silo, 473 * just reenable the transmitter. 474 */ 475 addr->csr = DMF_IE | DMFIR_TBUF | unit; 476 #ifdef new 477 if (addr->tsc || sc->dmx_dmacount[unit]) { 478 #else 479 if (addr->tsc) { 480 #endif 481 addr->csr = DMF_IE | DMFIR_LCR | unit; 482 addr->lctms = addr->lctms | DMF_TE; 483 tp->t_state |= TS_BUSY; 484 goto out; 485 } 486 /* 487 * If there are sleepers, and output has drained below low 488 * water mark, wake up the sleepers. 489 */ 490 if (tp->t_outq.c_cc <= tp->t_lowat) { 491 if (tp->t_state & TS_ASLEEP) { 492 tp->t_state &= ~TS_ASLEEP; 493 wakeup((caddr_t)&tp->t_outq); 494 } 495 if (tp->t_wsel) { 496 selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); 497 tp->t_wsel = 0; 498 tp->t_state &= ~TS_WCOLL; 499 } 500 } 501 /* 502 * Now restart transmission unless the output queue is 503 * empty. 504 */ 505 if (tp->t_outq.c_cc == 0) 506 goto out; 507 if (1 || !(tp->t_oflag&OPOST)) /*XXX*/ 508 nch = ndqb(&tp->t_outq, 0); 509 else { 510 if ((nch = ndqb(&tp->t_outq, 0200)) == 0) { 511 /* 512 * If first thing on queue is a delay process it. 513 */ 514 nch = getc(&tp->t_outq); 515 timeout(ttrstrt, (caddr_t)tp, (nch&0x7f)+6); 516 tp->t_state |= TS_TIMEOUT; 517 goto out; 518 } 519 } 520 /* 521 * If characters to transmit, restart transmission. 522 */ 523 if (nch >= dmx_mindma) { 524 register car; 525 526 sc->dmx_dmacount[unit] = nch; 527 addr->csr = DMF_IE | DMFIR_LCR | unit; 528 addr->lctms = addr->lctms | DMF_TE; 529 car = UBACVT(tp->t_outq.c_cf, sc->dmx_ubanum); 530 addr->csr = DMF_IE | DMFIR_TBA | unit; 531 addr->tba = car; 532 addr->tcc = ((car >> 2) & 0xc000) | nch; 533 tp->t_state |= TS_BUSY; 534 } else if (nch) { 535 register char *cp = tp->t_outq.c_cf; 536 register int i; 537 538 #ifndef new 539 sc->dmx_dmacount[unit] = 0; 540 #endif 541 nch = MIN(nch, DMF_SILOCNT); 542 addr->csr = DMF_IE | DMFIR_LCR | unit; 543 addr->lctms = addr->lctms | DMF_TE; 544 addr->csr = DMF_IE | DMFIR_TBUF | unit; 545 for (i = 0; i < nch; i++) 546 addr->tbuf = *cp++; 547 ndflush(&tp->t_outq, nch); 548 tp->t_state |= TS_BUSY; 549 } 550 out: 551 splx(s); 552 } 553 554 dmxstop(tp, sc, flag) 555 register struct tty *tp; 556 struct dmx_softc *sc; 557 { 558 register struct dmx_octet *addr; 559 register unit = minor(tp->t_dev) & 7; 560 int s; 561 562 addr = (struct dmx_octet *)tp->t_addr; 563 /* 564 * Block input/output interrupts while messing with state. 565 */ 566 s = spltty(); 567 if (flag) { 568 addr->csr = DMF_IE | DMFIR_TBUF | unit; 569 if (addr->tsc) { 570 /* 571 * Flush regardless of whether we're transmitting 572 * (TS_BUSY), if the silo contains untransmitted 573 * characters. 574 */ 575 addr->csr = DMFIR_LCR | unit | DMF_IE; 576 addr->lctms = addr->lctms | DMF_TE | DMF_FLUSH; 577 /* this will interrupt so let dmxxint handle the rest */ 578 tp->t_state |= TS_FLUSH|TS_BUSY; 579 } 580 /*#ifdef new*/ 581 sc->dmx_dmacount[unit] = 0; 582 /*#endif*/ 583 } else { 584 /* 585 * Stop transmission by disabling 586 * the transmitter. We'll pick up where we 587 * left off by reenabling in dmxstart. 588 */ 589 addr->csr = DMFIR_LCR | unit | DMF_IE; 590 addr->lctms = addr->lctms &~ DMF_TE; 591 /* no interrupt here */ 592 tp->t_state &= ~TS_BUSY; 593 } 594 splx(s); 595 } 596 #endif NDMF + NDMZ 597