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