1 /* 2 * Copyright (c) 1985 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 * @(#)dmz.c 6.3 (Berkeley) 11/08/85 7 */ 8 9 /* 10 * DMZ-32 driver 11 * HISTORY 12 * 23-Apr-85 Joe Camaratta (jcc) at Siemens RTL 13 * Driver for DEC's DMZ32 24-line asynchronous multiplexor. 14 * Based on Chris Maloney's driver for DEC's DMF32 15 * NOTE: The modem control routines have NOT been tested yet!!! 16 * 17 * 9-Aug-85 Mike Meyer (mwm) at ucb 18 * Mangled into shape for 4.3. 19 */ 20 21 #include "dmz.h" 22 #if NDMZ > 0 23 24 25 #include "../machine/pte.h" 26 27 28 #include "bk.h" 29 #include "uba.h" 30 #include "param.h" 31 #include "conf.h" 32 #include "dir.h" 33 #include "user.h" 34 #include "ioctl.h" 35 #include "tty.h" 36 #include "map.h" 37 #include "buf.h" 38 #include "vm.h" 39 #include "bkmac.h" 40 #include "clist.h" 41 #include "file.h" 42 #include "uio.h" 43 #include "kernel.h" 44 #include "syslog.h" 45 46 #include "ubareg.h" 47 #include "ubavar.h" 48 #include "dmzreg.h" 49 50 int dmzprobe(), dmzattach(), dmzrint(), dmzxint(); 51 struct uba_device *dmzinfo[NDMZ]; 52 u_short dmzstd[] = {0, 0}; 53 struct uba_driver dmzdriver = { 54 dmzprobe, 0, dmzattach, 0, dmzstd, "dmz", dmzinfo 55 }; 56 57 #define NDMZLINES (NDMZ*24) 58 59 int ttrstrt(); 60 struct tty dmz_tty[NDMZLINES]; 61 62 int dmzsoftCAR[NDMZ]; 63 64 struct { 65 char dmz_state; /* dmz state */ 66 int dmz_count; /* dmz dma count */ 67 } dmz_softc[NDMZ*24]; 68 69 #define ST_TXOFF (0x01) /* transmission turned off (^S) */ 70 #define ST_DMA (0x02) /* dma inprogress */ 71 #define ST_INBUSY (0x04) /* stop transmission in busy */ 72 73 char dmz_speeds[] = { 74 0, 0, 1, 2, 3, 4, 0, 5, 6, 7, 010, 012, 014, 016, 017, 0 75 }; 76 77 #ifndef PORTSELECTOR 78 #define ISPEED B9600 79 #define IFLAGS (EVENP|ODDP|ECHO) 80 #else 81 #define ISPEED B4800 82 #define IFLAGS (EVENP|ODDP) 83 #endif 84 85 #ifndef lint 86 int ndmz = NDMZLINES; /* Used by pstat/iostat */ 87 #endif 88 89 short dmzact[NDMZ]; /* Mask of active octets on the dmz */ 90 int dmzstart(); 91 92 /* 93 * SILO_TIMEOUT represents the number of milliseconds characters can sit 94 * in the input silo without causing an interrupt. If data overruns or 95 * slow XON/XOFF occur, set it lower but AT LEAST equal to 1. 96 */ 97 #define SILO_TIMEOUT (3) 98 99 /* 100 * DO_DMA_COUNT represents the threshold of the number of output 101 * characters beyond which the driver uses DMA mode. 102 */ 103 #define DO_DMA_COUNT (10) 104 105 #define TRUE (1) 106 #define FALSE (0) 107 108 int cbase[NUBA]; /* base address in unibus map */ 109 int dmz_ubinfo[NUBA]; /* info about allocated unibus map */ 110 111 #define UBACVT(x, uban) (cbase[uban] + ((x) - (char *)cfree)) 112 113 /* These flags are for debugging purposes only */ 114 int dmz_dma_on = 1; 115 int dmz_debug_level; 116 117 dmzprobe(reg) 118 caddr_t reg; 119 { 120 register int br, cvec; 121 register struct dmzdevice *dmz_addr; 122 register unsigned int a; 123 124 dmz_addr = (struct dmzdevice *)reg; 125 126 #ifdef lint 127 br = 0; cvec = br; br = cvec; dmzxinta(0); dmzxintb(0); dmzxintc(0); 128 dmzrinta(0); dmzrintb(0); dmzrintc(0); 129 #endif 130 131 br = 0x15; 132 133 a = dmz_addr->dmz_config; 134 if (((a>>12) & ~DMZ_INTERFACE) != 0) { 135 printf(" Unknown interface type\n"); 136 return (0); 137 } 138 if (((a>>8) & DMZ_NOC_MASK) != 3) { 139 printf(" Not all octets are available\n"); 140 return (0); 141 } 142 143 cvec = (uba_hd[numuba].uh_lastiv -= 4 * 6); 144 dmz_addr->dmz_config = cvec >> 2; 145 146 return (sizeof(struct dmzdevice)); 147 } 148 149 dmzattach(ui) 150 struct uba_device *ui; 151 { 152 dmzsoftCAR[ui->ui_unit] = ui->ui_flags; 153 return; 154 } 155 156 /* ARGSUSED */ 157 dmzopen(device, flag) 158 dev_t device; 159 int flag; 160 { 161 register struct tty *tp; 162 register int unit, controller; 163 register struct dmzdevice *dmz_addr; 164 register struct uba_device *ui; 165 int priority; 166 int octet; 167 168 unit = minor(device); 169 controller = DMZ(unit); 170 octet = OCTET(unit); 171 172 if (unit >= NDMZLINES || 173 (ui = dmzinfo[controller]) == 0 || 174 ui->ui_alive == 0) 175 return (ENXIO); 176 177 tp = &dmz_tty[unit]; 178 179 if ((tp->t_state & TS_XCLUDE) && u.u_uid != 0) 180 return (EBUSY); 181 182 dmz_addr = (struct dmzdevice *)ui->ui_addr; 183 tp->t_addr = (caddr_t)dmz_addr; 184 tp->t_oproc = dmzstart; 185 tp->t_state |= TS_WOPEN; 186 187 /* 188 * Set up Unibus map registers. Block uba resets, which can 189 * clear the state. 190 */ 191 priority = spl5(); 192 if (cbase[ui->ui_ubanum] == 0) { 193 dmz_ubinfo[ui->ui_ubanum] = 194 uballoc(ui->ui_ubanum, (caddr_t)cfree, 195 nclist * sizeof(struct cblock), 0); 196 if (dmz_ubinfo[ui->ui_ubanum] == 0) { 197 splx(priority); 198 printf("dmz: insufficient unibus map regs\n"); 199 return (ENOMEM); 200 } 201 cbase[ui->ui_ubanum] = dmz_ubinfo[ui->ui_ubanum] & 0x3ffff; 202 } 203 204 if ((dmzact[controller] & (1 << octet)) == 0) { 205 dmz_addr->octet[octet].octet_csr |= DMZ_IE; 206 dmzact[controller] |= 1 << octet; 207 dmz_addr->octet[octet].octet_receive.octet_sato = SILO_TIMEOUT; 208 } 209 210 splx(priority); 211 212 if ((tp->t_state & TS_ISOPEN) == 0) { 213 ttychars(tp); 214 tp->t_ispeed = tp->t_ospeed = ISPEED; 215 tp->t_flags = IFLAGS; 216 dmzparam(unit); 217 dmz_softc[unit].dmz_state = 0; 218 } 219 220 /* 221 * Wait for carrier, then process line discipline specific open. 222 */ 223 if ((dmzmctl(device, DMZ_ON, DMSET) & (DMZ_CAR << 8)) || 224 (dmzsoftCAR[controller] & (1 << (unit % 24)))) 225 tp->t_state |= TS_CARR_ON; 226 priority = spl5(); 227 while ((tp->t_state & TS_CARR_ON) == 0) { 228 tp->t_state |= TS_WOPEN; 229 sleep((caddr_t) &tp->t_rawq, TTIPRI); 230 } 231 splx(priority); 232 233 return ((*linesw[tp->t_line].l_open)(device, tp)); 234 } 235 236 dmzparam(unit) 237 register int unit; 238 { 239 register struct tty *tp; 240 register struct dmzdevice *dmz_addr; 241 register int line_parameters, line_control; 242 register int octet; 243 int priority; 244 245 octet = OCTET(unit); 246 247 tp = &dmz_tty[unit]; 248 dmz_addr = (struct dmzdevice *)tp->t_addr; 249 250 priority = spl5(); 251 if ((tp->t_ispeed) == 0) { 252 tp->t_state |= TS_HUPCLS; 253 (void) dmzmctl(unit, DMZ_OFF, DMSET); 254 splx(priority); 255 return; 256 } 257 258 line_parameters = (dmz_speeds[tp->t_ospeed] << 12) | (dmz_speeds[tp->t_ispeed] << 8); 259 line_control = DMZ_LCE; 260 261 if ((tp->t_ispeed) == B134) 262 line_parameters |= DMZ_6BT | DMZ_PEN; 263 else if (tp->t_flags & (RAW | LITOUT)) 264 line_parameters |= DMZ_8BT; 265 else 266 line_parameters |= DMZ_7BT | DMZ_PEN; 267 268 if (tp->t_flags & EVENP) 269 line_parameters |= DMZ_EPR; 270 if ((tp->t_ospeed) == B110) 271 line_parameters |= DMZ_SCD; 272 273 line_parameters |= (unit & 07); 274 275 dmz_addr->octet[octet].octet_lprm = line_parameters; 276 dmz_addr->octet[octet].octet_csr = DMZ_IE | IR_LCTMR | (unit & 07); 277 dmz_addr->octet[octet].octet_lctmr = 278 (dmz_addr->octet[octet].octet_lctmr | (line_control & 0xff)); 279 280 splx(priority); 281 return; 282 } 283 284 /* ARGSUSED */ 285 dmzclose(device, flag) 286 dev_t device; 287 int flag; 288 { 289 register struct tty *tp; 290 register int unit; 291 292 unit = minor(device); 293 tp = &dmz_tty[unit]; 294 295 /* 296 * Break, hang-up and close the modem. 297 */ 298 (void) dmzmctl(unit, DMZ_BRK, DMBIC); 299 if (tp->t_state & TS_HUPCLS || (tp->t_state & TS_ISOPEN) == 0) 300 (void) dmzmctl(unit, DMZ_OFF, DMSET); 301 ttyclose(tp); 302 return; 303 } 304 305 dmzreset(uban) 306 int uban; 307 { 308 register int controller, unit; 309 register struct tty *tp; 310 register struct uba_device *ui; 311 register struct dmzdevice *dmz_addr; 312 int i; 313 int octet; 314 315 for (controller = 0; controller < NDMZ; controller++) { 316 ui = dmzinfo[controller]; 317 if (ui == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban) 318 continue; 319 printf("dmz%d ", controller); 320 dmz_addr = (struct dmzdevice *) ui->ui_addr; 321 322 if (cbase[uban] == 0) { 323 dmz_ubinfo[uban] = uballoc(uban, (caddr_t)cfree, 324 nclist * sizeof(struct cblock), 0); 325 cbase[uban] = dmz_ubinfo[uban] & 0x3ffff; 326 } 327 328 for (octet = 0; octet < 3; octet++) 329 if ((dmzact[controller] & (1 << octet)) != 0) { 330 dmz_addr->octet[octet].octet_csr |= DMZ_IE; 331 dmz_addr->octet[octet].octet_receive.octet_sato = SILO_TIMEOUT; 332 } 333 334 unit = controller * 24; 335 336 /* 337 * If a unit is open or waiting for open to complete, 338 * reset it. 339 */ 340 for (i = 0; i < 24; i++) { 341 dmz_softc[unit].dmz_state = 0; 342 tp = &dmz_tty[unit]; 343 if (tp->t_state & (TS_ISOPEN | TS_WOPEN)) { 344 dmzparam(unit); 345 (void) dmzmctl(unit, DMZ_ON, DMSET); 346 tp->t_state &= ~TS_BUSY; 347 dmzstart(tp); 348 } 349 unit++; 350 } 351 } 352 return; 353 } 354 355 dmzread(device, uio) 356 dev_t device; 357 struct uio *uio; 358 { 359 register struct tty *tp; 360 int xstatus; 361 362 tp = &dmz_tty[minor(device)]; 363 xstatus = (*linesw[tp->t_line].l_read)(tp, uio); 364 return (xstatus); 365 } 366 367 dmzwrite(device, uio) 368 dev_t device; 369 struct uio *uio; 370 { 371 register struct tty *tp; 372 int xstatus; 373 374 tp = &dmz_tty[minor(device)]; 375 xstatus = (*linesw[tp->t_line].l_write)(tp, uio); 376 return (xstatus); 377 } 378 379 dmzrinta(controller) 380 int controller; 381 { 382 dmzrint(controller, 0); 383 } 384 385 dmzrintb(controller) 386 int controller; 387 { 388 dmzrint(controller, 1); 389 } 390 391 dmzrintc(controller) 392 int controller; 393 { 394 dmzrint(controller, 2); 395 } 396 397 dmzrint(controller, octet) 398 int controller; 399 register int octet; 400 { 401 register struct tty *tp; 402 register int character; 403 register struct dmzdevice *dmz_addr; 404 register struct tty *tp0; 405 register int unit; 406 register struct uba_device *ui; 407 int overrun; 408 409 overrun = 0; 410 ui = dmzinfo[controller]; 411 if (ui == 0 || ui->ui_alive == 0) 412 return; 413 dmz_addr = (struct dmzdevice *) ui->ui_addr; 414 tp0 = &dmz_tty[controller * 24]; 415 416 while ((character = dmz_addr->octet[octet].octet_receive.octet_rb) < 0) { 417 unit = (character >> 8) & 07; /* unit is bits 8-10 of rb */ 418 tp = tp0 + (octet * 8 + unit); 419 420 if (character & DMZ_DSC && 421 (dmzsoftCAR[controller] & (1 << (octet * 8 + unit))) == 0) { 422 dmz_addr->octet[octet].octet_csr = DMZ_IE | IR_RMS | unit; 423 if (dmz_addr->octet[octet].octet_rms & DMZ_CAR) 424 (void)(*linesw[tp->t_line].l_modem)(tp, 1); 425 else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0) { 426 dmz_addr->octet[octet].octet_csr = 427 DMZ_IE | IR_LCTMR | unit; 428 dmz_addr->octet[octet].octet_lctmr = 429 dmz_addr->octet[octet].octet_lctmr & 430 ((DMZ_OFF<<8) | 0xff); 431 } 432 continue; 433 } 434 435 if ((tp->t_state&TS_ISOPEN)==0) { 436 wakeup((caddr_t)&tp->t_rawq); 437 #ifdef PORTSELECTOR 438 if ((tp->t_state&TS_WOPEN) == 0) 439 #endif 440 continue; 441 } 442 443 if (character & DMZ_PE) { 444 if ((tp->t_flags & (EVENP | ODDP)) == EVENP || 445 (tp->t_flags & (EVENP | ODDP)) == ODDP) 446 continue; 447 } 448 449 if ((character & DMZ_DO) && overrun == 0) { 450 log(LOG_WARNING, "dmz%d: silo overflow\n", controller); 451 overrun = 1; 452 } 453 454 if (character & DMZ_FE) { 455 if (tp->t_flags & RAW) 456 character = 0; 457 else 458 character = tp->t_intrc; 459 } 460 461 (*linesw[tp->t_line].l_rint)(character, tp); 462 } 463 464 return; 465 } 466 467 dmzxinta(controller) 468 int controller; 469 { 470 dmzxint(controller, 0); 471 } 472 473 dmzxintb(controller) 474 int controller; 475 { 476 dmzxint(controller, 1); 477 } 478 479 dmzxintc(controller) 480 int controller; 481 { 482 dmzxint(controller, 2); 483 } 484 485 dmzxint(controller, octet) 486 int controller; 487 register int octet; 488 { 489 register struct tty *tp; 490 register struct dmzdevice *dmz_addr; 491 register struct uba_device *ui; 492 register int unit, t; 493 int priority; 494 495 ui = dmzinfo[controller]; 496 dmz_addr = (struct dmzdevice *)ui->ui_addr; 497 498 priority = spl5(); 499 500 while ((t = dmz_addr->octet[octet].octet_csr) & DMZ_TRDY) { 501 unit = controller * 24 + (octet * 8 + ((t>>8) & 07)); 502 tp = &dmz_tty[unit]; 503 tp->t_state &= ~TS_BUSY; 504 505 if (t & DMZ_NXM) 506 printf("dmz%d: NXM line %d\n", controller, 507 octet * 8 + (unit & 07)); 508 509 if (tp->t_state & TS_FLUSH) { 510 tp->t_state &= ~TS_FLUSH; 511 dmz_addr->octet[octet].octet_csr = 512 DMZ_IE | IR_LCTMR | (unit & 07); 513 dmz_addr->octet[octet].octet_lctmr = 514 (dmz_addr->octet[octet].octet_lctmr | DMZ_TE); 515 } else 516 if (dmz_softc[unit].dmz_state & ST_DMA) 517 ndflush(&tp->t_outq, dmz_softc[unit].dmz_count); 518 dmz_softc[unit].dmz_state = 0; 519 520 if (tp->t_line) 521 (*linesw[tp->t_line].l_start)(tp); 522 else 523 dmzstart(tp); 524 } 525 526 splx(priority); 527 return; 528 } 529 530 dmzstart(tp) 531 register struct tty *tp; 532 { 533 register struct dmzdevice *dmz_addr; 534 register int unit, nch, room; 535 int controller, octet; 536 int priority, car, use_dma; 537 register int i; 538 register char *cp; 539 540 unit = minor(tp->t_dev); 541 controller = DMZ(unit); 542 octet = OCTET(unit); 543 dmz_addr = (struct dmzdevice *)tp->t_addr; 544 545 priority = spl5(); 546 547 if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP)) 548 goto out; 549 550 /* 551 * If the transmitter has been disabled, reenable it. 552 * If the transmitter was disabled before the xint (the 553 * ST_INBUSY was still on), then reset the BUSY state and 554 * we will wait for the interrupt. If !TS_BUSY, we already 555 * saw the interrupt so we can start another transmission. 556 */ 557 if (dmz_softc[unit].dmz_state & ST_TXOFF) { 558 dmz_addr->octet[octet].octet_csr = 559 DMZ_IE | IR_LCTMR | (unit & 07); 560 dmz_addr->octet[octet].octet_lctmr = 561 (dmz_addr->octet[octet].octet_lctmr | DMZ_TE); 562 dmz_softc[unit].dmz_state &= ~ST_TXOFF; 563 if (dmz_softc[unit].dmz_state & ST_INBUSY) { 564 dmz_softc[unit].dmz_state &= ~ST_INBUSY; 565 tp->t_state |= TS_BUSY; 566 goto out; 567 } 568 } 569 570 if (tp->t_outq.c_cc <= TTLOWAT(tp)) { 571 if (tp->t_state & TS_ASLEEP) { 572 tp->t_state &= ~TS_ASLEEP; 573 wakeup((caddr_t)&tp->t_outq); 574 } 575 if (tp->t_wsel) { 576 selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); 577 tp->t_wsel = 0; 578 tp->t_state &= ~TS_WCOLL; 579 } 580 } 581 582 if (tp->t_outq.c_cc == 0) 583 goto out; 584 if (tp->t_flags & (RAW | LITOUT)) 585 nch = ndqb(&tp->t_outq, 0); 586 else { 587 nch = ndqb(&tp->t_outq, 0200); 588 if (nch == 0) { 589 nch = getc(&tp->t_outq); 590 timeout(ttrstrt, (caddr_t)tp, (nch & 0x7f)+6); 591 tp->t_state |= TS_TIMEOUT; 592 goto out; 593 } 594 } 595 596 /* 597 * Should we use DMA or SILO mode? 598 * If nch is greater than DO_DMA_COUNT then DMA. 599 */ 600 if (nch) { 601 dmz_addr->octet[octet].octet_csr = 602 DMZ_IE | IR_LCTMR | (unit & 07); 603 dmz_addr->octet[octet].octet_lctmr = 604 (dmz_addr->octet[octet].octet_lctmr | DMZ_TE); 605 tp->t_state |= TS_BUSY; 606 607 use_dma = FALSE; 608 room = DMZ_SIZ; 609 610 if (nch > DO_DMA_COUNT) 611 use_dma = TRUE; 612 613 if (use_dma && dmz_dma_on) { 614 car = UBACVT(tp->t_outq.c_cf, 615 dmzinfo[controller]->ui_ubanum); 616 dmz_softc[unit].dmz_count = nch; 617 dmz_softc[unit].dmz_state |= ST_DMA; 618 dmz_addr->octet[octet].octet_csr = 619 DMZ_IE | IR_TBA | (unit & 07); 620 dmz_addr->octet[octet].octet_tba = car; 621 dmz_addr->octet[octet].octet_tcc = 622 ((car >> 2) & 0xc000) | nch; 623 } else { 624 dmz_softc[unit].dmz_state &= ~ST_DMA; 625 cp = tp->t_outq.c_cf; 626 nch = MIN(nch, room); 627 dmz_addr->octet[octet].octet_csr = 628 DMZ_IE | IR_TBUF | (unit & 07); 629 for (i = 0; i < nch; i++) 630 dmz_addr->octet[octet].octet_tbf = *cp++ ; 631 ndflush(&tp->t_outq, nch); 632 } 633 } 634 635 out: 636 splx(priority); 637 return; 638 } 639 640 /* ARGSUSED */ 641 dmzstop(tp, flag) 642 register struct tty *tp; 643 { 644 register struct dmzdevice *dmz_addr; 645 register int unit, priority, octet; 646 647 priority = spl5(); 648 dmz_addr = (struct dmzdevice *) tp->t_addr; 649 unit = minor(tp->t_dev); 650 octet = OCTET(unit); 651 652 dmz_addr->octet[octet].octet_csr = IR_LCTMR | (unit & 07) | DMZ_IE; 653 dmz_addr->octet[octet].octet_lctmr = 654 (dmz_addr->octet[octet].octet_lctmr & ~DMZ_TE); 655 dmz_softc[unit].dmz_state |= ST_TXOFF; 656 if ((tp->t_state & TS_TTSTOP) == 0) { 657 tp->t_state |= (TS_FLUSH | TS_BUSY); 658 dmz_addr->octet[octet].octet_lctmr = 659 (dmz_addr->octet[octet].octet_lctmr | DMZ_FLS); 660 } else if (tp->t_state & TS_BUSY) { 661 dmz_softc[unit].dmz_state |= ST_INBUSY; 662 tp->t_state &= ~TS_BUSY; 663 } 664 665 splx(priority); 666 return; 667 } 668 669 /* ARGSUSED */ 670 dmzioctl(device, command, data, flag) 671 dev_t device; 672 caddr_t data; 673 { 674 register struct tty *tp; 675 register int unit; 676 int error; 677 678 unit = minor(device); 679 tp = &dmz_tty[unit]; 680 681 error = (*linesw[tp->t_line].l_ioctl)(tp, command, data, flag); 682 if (error >= 0) 683 return (error); 684 error = ttioctl(tp, command, data, flag); 685 if (error >= 0) { 686 if (command == TIOCSETP || command == TIOCSETN) 687 dmzparam(unit); 688 return (error); 689 } 690 691 switch (command) { 692 case TIOCSBRK: 693 (void) dmzmctl(device, DMZ_BRK, DMBIS); 694 break; 695 case TIOCCBRK: 696 (void) dmzmctl(device, DMZ_BRK, DMBIC); 697 break; 698 case TIOCSDTR: 699 (void) dmzmctl(device, DMZ_DTR | DMZ_RTS, DMBIS); 700 break; 701 case TIOCCDTR: 702 (void) dmzmctl(device, DMZ_DTR | DMZ_RTS, DMBIC); 703 break; 704 case TIOCMSET: 705 (void) dmzmctl(device, dmtodmz(*(int *)data), DMSET); 706 break; 707 case TIOCMBIS: 708 (void) dmzmctl(device, dmtodmz(*(int *)data), DMBIS); 709 break; 710 case TIOCMBIC: 711 (void) dmzmctl(device, dmtodmz(*(int *)data), DMBIC); 712 break; 713 case TIOCMGET: 714 *(int *)data = dmztodm(dmzmctl(device, 0, DMGET)); 715 break; 716 default: 717 return (ENOTTY); 718 } 719 return (0); 720 } 721 722 dmzmctl(device, bits, how) 723 dev_t device; 724 int bits, how; 725 { 726 register struct dmzdevice *dmz_addr; 727 register int unit, modem_status, line_control; 728 register int temp; 729 int priority; 730 int octet; 731 732 unit = minor(device); 733 octet = OCTET(unit); 734 dmz_addr = (struct dmzdevice *) dmz_tty[unit].t_addr; 735 736 priority = spl5(); 737 dmz_addr->octet[octet].octet_csr = DMZ_IE | IR_RMS | (unit & 07); 738 modem_status = dmz_addr->octet[octet].octet_rms << 8; 739 740 dmz_addr->octet[octet].octet_csr = DMZ_IE | IR_LCTMR | (unit & 07); 741 temp = dmz_addr->octet[octet].octet_lctmr; 742 modem_status |= ((temp>>8) & (0x1f)); 743 line_control = (temp & (0x3f)); 744 745 if (line_control & DMZ_RBK) 746 modem_status |= DMZ_BRK; 747 748 switch (how) { 749 case DMSET: 750 modem_status = (modem_status & 0xff00) | bits; 751 break; 752 case DMBIS: 753 modem_status |= bits; 754 break; 755 case DMBIC: 756 modem_status &= ~bits; 757 break; 758 case DMGET: 759 (void) splx(priority); 760 return (modem_status); 761 } 762 763 if (modem_status & DMZ_BRK) 764 line_control |= DMZ_RBK; 765 else 766 line_control &= ~DMZ_RBK; 767 modem_status &= ~DMZ_BRK; 768 769 dmz_addr->octet[octet].octet_csr = 770 DMZ_IE | IR_LCTMR | (unit & 07); 771 dmz_addr->octet[octet].octet_lctmr = 772 ((modem_status & 0x1f) << 8) | (line_control & 0x3f); 773 774 (void) splx(priority); 775 return (modem_status); 776 } 777 778 /* 779 * Routine to convert modem status from dm to dmz format. 780 * Pull bits 1 & 3 through unchanged. If dm secondary transmit bit is set, 781 * and/or dm request to send bit is set, and/or dm user modem signal bit 782 * is set, set the corresponding dmz bits. 783 */ 784 dmtodmz(bits) 785 register int bits; 786 { 787 register int b; 788 789 b = bits & 012; 790 if (bits & DM_ST) 791 b |= DMZ_RAT; 792 if (bits & DM_RTS) 793 b |= DMZ_RTS; 794 if (bits & DM_USR) 795 b |= DMZ_USW; 796 return (b); 797 } 798 799 /* 800 * Routine to convert modem status from dmz to dm format. Pull bits 1 & 3 801 * through unchanged. Pull bits 11 - 15 through as bits 4 - 8 and set bit 802 * 0 to dm line enable. If dmz user modem signal bit set, and/or dmz 803 * request to send bit set, then set the corresponding dm bit also. 804 */ 805 dmztodm(bits) 806 register int bits; 807 { 808 register int b; 809 810 b = (bits & 012) | ((bits >> 7) & 0760) | DM_LE; 811 if (bits & DMZ_USR) 812 b |= DM_USR; 813 if (bits & DMZ_RTS) 814 b |= DM_RTS; 815 return (b); 816 } 817 #endif 818