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.5 (Berkeley) 02/17/86 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 * 16 * 9-Aug-85 Mike Meyer (mwm) at ucb 17 * Mangled into shape for 4.3. 18 */ 19 20 #include "dmz.h" 21 #if NDMZ > 0 22 23 24 #include "../machine/pte.h" 25 26 27 #include "bk.h" 28 #include "uba.h" 29 #include "param.h" 30 #include "conf.h" 31 #include "dir.h" 32 #include "user.h" 33 #include "ioctl.h" 34 #include "tty.h" 35 #include "map.h" 36 #include "buf.h" 37 #include "vm.h" 38 #include "bkmac.h" 39 #include "clist.h" 40 #include "file.h" 41 #include "uio.h" 42 #include "kernel.h" 43 #include "syslog.h" 44 45 #include "ubareg.h" 46 #include "ubavar.h" 47 #include "dmzreg.h" 48 #include "dmreg.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 cbase[ui->ui_ubanum] = -1; 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 186 /* 187 * Set up Unibus map registers. Block uba resets, which can 188 * clear the state. 189 */ 190 priority = spl5(); 191 if (cbase[ui->ui_ubanum] == -1) { 192 dmz_ubinfo[ui->ui_ubanum] = 193 uballoc(ui->ui_ubanum, (caddr_t)cfree, 194 nclist * sizeof(struct cblock), 0); 195 if (dmz_ubinfo[ui->ui_ubanum] == 0) { 196 splx(priority); 197 printf("dmz: insufficient unibus map regs\n"); 198 return (ENOMEM); 199 } 200 cbase[ui->ui_ubanum] = UBAI_ADDR(dmz_ubinfo[ui->ui_ubanum]); 201 } 202 203 if ((dmzact[controller] & (1 << octet)) == 0) { 204 dmz_addr->octet[octet].octet_csr |= DMZ_IE; 205 dmzact[controller] |= 1 << octet; 206 dmz_addr->octet[octet].octet_receive.octet_sato = SILO_TIMEOUT; 207 } 208 209 splx(priority); 210 211 if ((tp->t_state & TS_ISOPEN) == 0) { 212 ttychars(tp); 213 tp->t_ispeed = tp->t_ospeed = ISPEED; 214 tp->t_flags = IFLAGS; 215 dmz_softc[unit].dmz_state = 0; 216 } 217 dmzparam(unit); 218 219 /* 220 * Wait for carrier, then process line discipline specific open. 221 */ 222 if ((dmzmctl(unit, DMZ_ON, DMSET) & DMZ_CAR) || 223 (dmzsoftCAR[controller] & (1 << (unit % 24)))) 224 tp->t_state |= TS_CARR_ON; 225 priority = spl5(); 226 while ((tp->t_state & TS_CARR_ON) == 0) { 227 tp->t_state |= TS_WOPEN; 228 sleep((caddr_t) &tp->t_rawq, TTIPRI); 229 } 230 splx(priority); 231 232 return ((*linesw[tp->t_line].l_open)(device, tp)); 233 } 234 235 dmzparam(unit) 236 register int unit; 237 { 238 register struct tty *tp; 239 register struct dmzdevice *dmz_addr; 240 register int line_parameters; 241 register int octet; 242 int priority; 243 244 octet = OCTET(unit); 245 246 tp = &dmz_tty[unit]; 247 dmz_addr = (struct dmzdevice *)tp->t_addr; 248 249 priority = spl5(); 250 if ((tp->t_ispeed) == 0) { 251 tp->t_state |= TS_HUPCLS; 252 (void) dmzmctl(unit, DMZ_OFF, DMSET); 253 splx(priority); 254 return; 255 } 256 257 line_parameters = (dmz_speeds[tp->t_ospeed] << 12) | (dmz_speeds[tp->t_ispeed] << 8); 258 259 if ((tp->t_ispeed) == B134) 260 line_parameters |= DMZ_6BT | DMZ_PEN; 261 else if (tp->t_flags & (RAW | LITOUT | PASS8)) 262 line_parameters |= DMZ_8BT; 263 else 264 line_parameters |= DMZ_7BT | DMZ_PEN; 265 266 if (tp->t_flags & EVENP) 267 line_parameters |= DMZ_EPR; 268 if ((tp->t_ospeed) == B110) 269 line_parameters |= DMZ_SCD; 270 271 line_parameters |= (unit & 07); 272 273 dmz_addr->octet[octet].octet_lprm = line_parameters; 274 splx(priority); 275 } 276 277 /* ARGSUSED */ 278 dmzclose(device, flag) 279 dev_t device; 280 int flag; 281 { 282 register struct tty *tp; 283 register int unit; 284 285 unit = minor(device); 286 tp = &dmz_tty[unit]; 287 (*linesw[tp->t_line].l_close)(tp); 288 289 /* 290 * Clear break, hang-up and close the modem. 291 */ 292 (void) dmzmctl(unit, DMZ_BRK, DMBIC); 293 if (tp->t_state & TS_HUPCLS || (tp->t_state & TS_ISOPEN) == 0) 294 (void) dmzmctl(unit, DMZ_OFF, DMSET); 295 ttyclose(tp); 296 return; 297 } 298 299 dmzreset(uban) 300 int uban; 301 { 302 register int controller, unit; 303 register struct tty *tp; 304 register struct uba_device *ui; 305 register struct dmzdevice *dmz_addr; 306 int i; 307 int octet; 308 309 for (controller = 0; controller < NDMZ; controller++) { 310 ui = dmzinfo[controller]; 311 if (ui == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban) 312 continue; 313 printf("dmz%d ", controller); 314 dmz_addr = (struct dmzdevice *) ui->ui_addr; 315 316 if (dmz_ubinfo[uban]) { 317 dmz_ubinfo[uban] = uballoc(uban, (caddr_t)cfree, 318 nclist * sizeof(struct cblock), 0); 319 cbase[uban] = UBAI_ADDR(dmz_ubinfo[uban]); 320 } 321 322 for (octet = 0; octet < 3; octet++) 323 if ((dmzact[controller] & (1 << octet)) != 0) { 324 dmz_addr->octet[octet].octet_csr |= DMZ_IE; 325 dmz_addr->octet[octet].octet_receive.octet_sato = SILO_TIMEOUT; 326 } 327 328 unit = controller * 24; 329 330 /* 331 * If a unit is open or waiting for open to complete, 332 * reset it. 333 */ 334 for (i = 0; i < 24; i++) { 335 dmz_softc[unit].dmz_state = 0; 336 tp = &dmz_tty[unit]; 337 if (tp->t_state & (TS_ISOPEN | TS_WOPEN)) { 338 dmzparam(unit); 339 (void) dmzmctl(unit, DMZ_ON, DMSET); 340 tp->t_state &= ~TS_BUSY; 341 dmzstart(tp); 342 } 343 unit++; 344 } 345 } 346 return; 347 } 348 349 dmzread(device, uio) 350 dev_t device; 351 struct uio *uio; 352 { 353 register struct tty *tp; 354 int xstatus; 355 356 tp = &dmz_tty[minor(device)]; 357 xstatus = (*linesw[tp->t_line].l_read)(tp, uio); 358 return (xstatus); 359 } 360 361 dmzwrite(device, uio) 362 dev_t device; 363 struct uio *uio; 364 { 365 register struct tty *tp; 366 int xstatus; 367 368 tp = &dmz_tty[minor(device)]; 369 xstatus = (*linesw[tp->t_line].l_write)(tp, uio); 370 return (xstatus); 371 } 372 373 dmzrinta(controller) 374 int controller; 375 { 376 dmzrint(controller, 0); 377 } 378 379 dmzrintb(controller) 380 int controller; 381 { 382 dmzrint(controller, 1); 383 } 384 385 dmzrintc(controller) 386 int controller; 387 { 388 dmzrint(controller, 2); 389 } 390 391 dmzrint(controller, octet) 392 int controller; 393 register int octet; 394 { 395 register struct tty *tp; 396 register int character; 397 register struct dmzdevice *dmz_addr; 398 register struct tty *tp0; 399 register int unit; 400 register struct uba_device *ui; 401 int overrun; 402 403 overrun = 0; 404 ui = dmzinfo[controller]; 405 if (ui == 0 || ui->ui_alive == 0) 406 return; 407 dmz_addr = (struct dmzdevice *) ui->ui_addr; 408 tp0 = &dmz_tty[controller * 24]; 409 410 while ((character = dmz_addr->octet[octet].octet_receive.octet_rb) < 0) { 411 unit = (character >> 8) & 07; /* unit is bits 8-10 of rb */ 412 tp = tp0 + (octet * 8 + unit); 413 414 if (character & DMZ_DSC) { 415 dmz_addr->octet[octet].octet_csr = DMZ_IE | IR_RMSTSC | unit; 416 if (dmz_addr->octet[octet].octet_rmstsc & DMZ_CAR) 417 (void)(*linesw[tp->t_line].l_modem)(tp, 1); 418 else if (dmzsoftCAR[controller] & 419 (1 << (octet * 8 + unit)) == 0 && 420 (*linesw[tp->t_line].l_modem)(tp, 0) == 0) 421 (void)dmzmctl(tp - dmz_tty, DMZ_OFF, DMSET); 422 continue; 423 } 424 425 if ((tp->t_state&TS_ISOPEN)==0) { 426 wakeup((caddr_t)&tp->t_rawq); 427 #ifdef PORTSELECTOR 428 if ((tp->t_state&TS_WOPEN) == 0) 429 #endif 430 continue; 431 } 432 433 if (character & DMZ_PE) { 434 if ((tp->t_flags & (EVENP | ODDP)) == EVENP || 435 (tp->t_flags & (EVENP | ODDP)) == ODDP) 436 continue; 437 } 438 439 if ((character & DMZ_DO) && overrun == 0) { 440 log(LOG_WARNING, "dmz%d: silo overflow\n", controller); 441 overrun = 1; 442 } 443 444 if (character & DMZ_FE) { 445 if (tp->t_flags & RAW) 446 character = 0; 447 else 448 character = tp->t_intrc; 449 } 450 451 (*linesw[tp->t_line].l_rint)(character, tp); 452 } 453 454 return; 455 } 456 457 dmzxinta(controller) 458 int controller; 459 { 460 dmzxint(controller, 0); 461 } 462 463 dmzxintb(controller) 464 int controller; 465 { 466 dmzxint(controller, 1); 467 } 468 469 dmzxintc(controller) 470 int controller; 471 { 472 dmzxint(controller, 2); 473 } 474 475 dmzxint(controller, octet) 476 int controller; 477 register int octet; 478 { 479 register struct tty *tp; 480 register struct dmzdevice *dmz_addr; 481 register struct uba_device *ui; 482 register int unit, t; 483 int priority; 484 485 ui = dmzinfo[controller]; 486 dmz_addr = (struct dmzdevice *)ui->ui_addr; 487 488 priority = spl5(); 489 490 while ((t = dmz_addr->octet[octet].octet_csr) & DMZ_TRDY) { 491 unit = controller * 24 + (octet * 8 + ((t>>8) & 07)); 492 tp = &dmz_tty[unit]; 493 tp->t_state &= ~TS_BUSY; 494 495 if (t & DMZ_NXM) 496 printf("dmz%d: NXM line %d\n", controller, 497 octet * 8 + (unit & 07)); 498 499 if (tp->t_state & TS_FLUSH) { 500 tp->t_state &= ~TS_FLUSH; 501 dmz_addr->octet[octet].octet_csr = 502 DMZ_IE | IR_LCTMR | (unit & 07); 503 dmz_addr->octet[octet].octet_lctmr = 504 (dmz_addr->octet[octet].octet_lctmr | DMZ_TE); 505 } else 506 if (dmz_softc[unit].dmz_state & ST_DMA) 507 ndflush(&tp->t_outq, dmz_softc[unit].dmz_count); 508 dmz_softc[unit].dmz_state = 0; 509 510 if (tp->t_line) 511 (*linesw[tp->t_line].l_start)(tp); 512 else 513 dmzstart(tp); 514 } 515 516 splx(priority); 517 return; 518 } 519 520 dmzstart(tp) 521 register struct tty *tp; 522 { 523 register struct dmzdevice *dmz_addr; 524 register int unit, nch, room; 525 int controller, octet; 526 int priority, car, use_dma; 527 register int i; 528 register char *cp; 529 530 unit = minor(tp->t_dev); 531 controller = DMZ(unit); 532 octet = OCTET(unit); 533 dmz_addr = (struct dmzdevice *)tp->t_addr; 534 535 priority = spl5(); 536 537 if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP)) 538 goto out; 539 540 /* 541 * If the transmitter has been disabled, reenable it. 542 * If the transmitter was disabled before the xint (the 543 * ST_INBUSY was still on), then reset the BUSY state and 544 * we will wait for the interrupt. If !TS_BUSY, we already 545 * saw the interrupt so we can start another transmission. 546 */ 547 if (dmz_softc[unit].dmz_state & ST_TXOFF) { 548 dmz_addr->octet[octet].octet_csr = 549 DMZ_IE | IR_LCTMR | (unit & 07); 550 dmz_addr->octet[octet].octet_lctmr = 551 (dmz_addr->octet[octet].octet_lctmr | DMZ_TE); 552 dmz_softc[unit].dmz_state &= ~ST_TXOFF; 553 if (dmz_softc[unit].dmz_state & ST_INBUSY) { 554 dmz_softc[unit].dmz_state &= ~ST_INBUSY; 555 tp->t_state |= TS_BUSY; 556 goto out; 557 } 558 } 559 560 if (tp->t_outq.c_cc <= TTLOWAT(tp)) { 561 if (tp->t_state & TS_ASLEEP) { 562 tp->t_state &= ~TS_ASLEEP; 563 wakeup((caddr_t)&tp->t_outq); 564 } 565 if (tp->t_wsel) { 566 selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); 567 tp->t_wsel = 0; 568 tp->t_state &= ~TS_WCOLL; 569 } 570 } 571 572 if (tp->t_outq.c_cc == 0) 573 goto out; 574 if (tp->t_flags & (RAW | LITOUT | PASS8)) 575 nch = ndqb(&tp->t_outq, 0); 576 else { 577 nch = ndqb(&tp->t_outq, 0200); 578 if (nch == 0) { 579 nch = getc(&tp->t_outq); 580 timeout(ttrstrt, (caddr_t)tp, (nch & 0x7f)+6); 581 tp->t_state |= TS_TIMEOUT; 582 goto out; 583 } 584 } 585 586 /* 587 * Should we use DMA or SILO mode? 588 * If nch is greater than DO_DMA_COUNT then DMA. 589 */ 590 if (nch) { 591 dmz_addr->octet[octet].octet_csr = 592 DMZ_IE | IR_LCTMR | (unit & 07); 593 dmz_addr->octet[octet].octet_lctmr = 594 (dmz_addr->octet[octet].octet_lctmr | DMZ_TE); 595 tp->t_state |= TS_BUSY; 596 597 use_dma = FALSE; 598 room = DMZ_SIZ; 599 600 if (nch > DO_DMA_COUNT) 601 use_dma = TRUE; 602 603 if (use_dma && dmz_dma_on) { 604 car = UBACVT(tp->t_outq.c_cf, 605 dmzinfo[controller]->ui_ubanum); 606 dmz_softc[unit].dmz_count = nch; 607 dmz_softc[unit].dmz_state |= ST_DMA; 608 dmz_addr->octet[octet].octet_csr = 609 DMZ_IE | IR_TBA | (unit & 07); 610 dmz_addr->octet[octet].octet_tba = car; 611 dmz_addr->octet[octet].octet_tcc = 612 ((car >> 2) & 0xc000) | nch; 613 } else { 614 dmz_softc[unit].dmz_state &= ~ST_DMA; 615 cp = tp->t_outq.c_cf; 616 nch = MIN(nch, room); 617 dmz_addr->octet[octet].octet_csr = 618 DMZ_IE | IR_TBUF | (unit & 07); 619 for (i = 0; i < nch; i++) 620 dmz_addr->octet[octet].octet_tbf = *cp++ ; 621 ndflush(&tp->t_outq, nch); 622 } 623 } 624 625 out: 626 splx(priority); 627 return; 628 } 629 630 /* ARGSUSED */ 631 dmzstop(tp, flag) 632 register struct tty *tp; 633 { 634 register struct dmzdevice *dmz_addr; 635 register int unit, priority, octet; 636 637 priority = spl5(); 638 dmz_addr = (struct dmzdevice *) tp->t_addr; 639 unit = minor(tp->t_dev); 640 octet = OCTET(unit); 641 642 dmz_addr->octet[octet].octet_csr = IR_LCTMR | (unit & 07) | DMZ_IE; 643 dmz_addr->octet[octet].octet_lctmr = 644 (dmz_addr->octet[octet].octet_lctmr & ~DMZ_TE); 645 dmz_softc[unit].dmz_state |= ST_TXOFF; 646 if ((tp->t_state & TS_TTSTOP) == 0) { 647 tp->t_state |= (TS_FLUSH | TS_BUSY); 648 dmz_addr->octet[octet].octet_lctmr = 649 (dmz_addr->octet[octet].octet_lctmr | DMZ_FLS); 650 } else if (tp->t_state & TS_BUSY) { 651 dmz_softc[unit].dmz_state |= ST_INBUSY; 652 tp->t_state &= ~TS_BUSY; 653 } 654 655 splx(priority); 656 return; 657 } 658 659 /* ARGSUSED */ 660 dmzioctl(device, command, data, flag) 661 dev_t device; 662 caddr_t data; 663 { 664 register struct tty *tp; 665 register int unit; 666 int error; 667 668 unit = minor(device); 669 tp = &dmz_tty[unit]; 670 671 error = (*linesw[tp->t_line].l_ioctl)(tp, command, data, flag); 672 if (error >= 0) 673 return (error); 674 error = ttioctl(tp, command, data, flag); 675 if (error >= 0) { 676 if (command == TIOCSETP || command == TIOCSETN || 677 command == TIOCLSET || command == TIOCLBIS || 678 command == TIOCLBIC) 679 dmzparam(unit); 680 return (error); 681 } 682 683 switch (command) { 684 case TIOCSBRK: 685 (void) dmzmctl(unit, DMZ_BRK, DMBIS); 686 break; 687 case TIOCCBRK: 688 (void) dmzmctl(unit, DMZ_BRK, DMBIC); 689 break; 690 case TIOCSDTR: 691 (void) dmzmctl(unit, DMZ_DTR | DMZ_RTS, DMBIS); 692 break; 693 case TIOCCDTR: 694 (void) dmzmctl(unit, DMZ_DTR | DMZ_RTS, DMBIC); 695 break; 696 case TIOCMSET: 697 (void) dmzmctl(unit, dmtodmz(*(int *)data), DMSET); 698 break; 699 case TIOCMBIS: 700 (void) dmzmctl(unit, dmtodmz(*(int *)data), DMBIS); 701 break; 702 case TIOCMBIC: 703 (void) dmzmctl(unit, dmtodmz(*(int *)data), DMBIC); 704 break; 705 case TIOCMGET: 706 *(int *)data = dmzmctl(unit, 0, DMGET); 707 break; 708 default: 709 return (ENOTTY); 710 } 711 return (0); 712 } 713 714 dmzmctl(unit, bits, how) 715 register int unit; 716 int bits, how; 717 { 718 register struct dmzdevice *dmz_addr; 719 register int modem_status, line_control; 720 int priority; 721 int octet; 722 723 octet = OCTET(unit); 724 dmz_addr = (struct dmzdevice *) dmzinfo[DMZ(unit)]->ui_addr; 725 726 priority = spl5(); 727 dmz_addr->octet[octet].octet_csr = DMZ_IE | IR_RMSTSC | (unit & 07); 728 modem_status = dmz_addr->octet[octet].octet_rmstsc & 0xff00; 729 730 dmz_addr->octet[octet].octet_csr = DMZ_IE | IR_LCTMR | (unit & 07); 731 line_control = dmz_addr->octet[octet].octet_lctmr; 732 733 734 switch (how) { 735 case DMSET: 736 line_control = bits; 737 break; 738 case DMBIS: 739 line_control |= bits; 740 break; 741 case DMBIC: 742 line_control &= ~bits; 743 break; 744 case DMGET: 745 (void) splx(priority); 746 return (dmztodm(modem_status, line_control)); 747 } 748 749 dmz_addr->octet[octet].octet_csr = 750 DMZ_IE | IR_LCTMR | (unit & 07); 751 dmz_addr->octet[octet].octet_lctmr = line_control; 752 753 splx(priority); 754 return (modem_status); 755 } 756 757 /* 758 * Routine to convert modem status from dm to dmz lctmr format. 759 */ 760 dmtodmz(bits) 761 register int bits; 762 { 763 register int lcr = DMZ_LCE; 764 765 if (bits & DML_DTR) 766 lcr |= DMZ_DTR; 767 if (bits & DML_RTS) 768 lcr |= DMZ_RTS; 769 if (bits & DML_ST) 770 lcr |= DMF_ST; 771 if (bits & DML_USR) 772 lcr |= DMZ_USRW; 773 return (lcr); 774 } 775 776 /* 777 * Routine to convert modem status from dmz receive modem status 778 * and line control register to dm format. 779 * If dmz user modem read bit set, set DML_USR. 780 */ 781 dmztodm(rms, lcr) 782 register int rms, lcr; 783 { 784 785 rms = ((rms & (DMZ_DSR|DMZ_RNG|DMZ_CAR|DMZ_CTS|DMF_SR)) >> 7) | 786 ((rms & DMZ_USRR) >> 1) | DML_LE; 787 if (lcr & DMZ_DTR) 788 rms |= DML_DTR; 789 if (lcr & DMF_ST) 790 rms |= DML_ST; 791 if (lcr & DMZ_RTS) 792 rms |= DML_RTS; 793 return (rms); 794 } 795 #endif 796