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