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.8 (Berkeley) 04/26/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 "proc.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 #include "dmreg.h" 50 51 int dmzprobe(), dmzattach(), dmzrint(), dmzxint(); 52 struct uba_device *dmzinfo[NDMZ]; 53 u_short dmzstd[] = {0, 0}; 54 struct uba_driver dmzdriver = { 55 dmzprobe, 0, dmzattach, 0, dmzstd, "dmz", dmzinfo 56 }; 57 58 #define NDMZLINES (NDMZ*24) 59 60 int ttrstrt(); 61 struct tty dmz_tty[NDMZLINES]; 62 63 int dmzsoftCAR[NDMZ]; 64 65 struct { 66 char dmz_state; /* dmz state */ 67 int dmz_count; /* dmz dma count */ 68 } dmz_softc[NDMZ*24]; 69 70 #define ST_TXOFF (0x01) /* transmission turned off (^S) */ 71 #define ST_DMA (0x02) /* dma inprogress */ 72 #define ST_INBUSY (0x04) /* stop transmission in busy */ 73 74 char dmz_speeds[] = { 75 0, 0, 1, 2, 3, 4, 0, 5, 6, 7, 010, 012, 014, 016, 017, 0 76 }; 77 78 #ifndef PORTSELECTOR 79 #define ISPEED B9600 80 #define IFLAGS (EVENP|ODDP|ECHO) 81 #else 82 #define ISPEED B4800 83 #define IFLAGS (EVENP|ODDP) 84 #endif 85 86 #ifndef lint 87 int ndmz = NDMZLINES; /* Used by pstat/iostat */ 88 #endif 89 90 short dmzact[NDMZ]; /* Mask of active octets on the dmz */ 91 int dmzstart(); 92 93 /* 94 * SILO_TIMEOUT represents the number of milliseconds characters can sit 95 * in the input silo without causing an interrupt. If data overruns or 96 * slow XON/XOFF occur, set it lower but AT LEAST equal to 1. 97 */ 98 #define SILO_TIMEOUT (3) 99 100 /* 101 * DO_DMA_COUNT represents the threshold of the number of output 102 * characters beyond which the driver uses DMA mode. 103 */ 104 #define DO_DMA_COUNT (10) 105 106 #define TRUE (1) 107 #define FALSE (0) 108 109 int cbase[NUBA]; /* base address in unibus map */ 110 int dmz_ubinfo[NUBA]; /* info about allocated unibus map */ 111 112 #define UBACVT(x, uban) (cbase[uban] + ((x) - (char *)cfree)) 113 114 /* These flags are for debugging purposes only */ 115 int dmz_dma_on = 1; 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 #ifndef PORTSELECTOR 214 if (tp->t_ispeed == 0) { 215 #else 216 tp->t_state |= TS_HUPCLS; 217 #endif PORTSELECTOR 218 tp->t_ispeed = ISPEED; 219 tp->t_ospeed = ISPEED; 220 tp->t_flags = IFLAGS; 221 #ifndef PORTSELECTOR 222 } 223 #endif PORTSELECTOR 224 dmz_softc[unit].dmz_state = 0; 225 } 226 dmzparam(unit); 227 228 /* 229 * Wait for carrier, then process line discipline specific open. 230 */ 231 if ((dmzmctl(unit, DMZ_ON, DMSET) & DMZ_CAR) || 232 (dmzsoftCAR[controller] & (1 << (unit % 24)))) 233 tp->t_state |= TS_CARR_ON; 234 priority = spl5(); 235 while ((tp->t_state & TS_CARR_ON) == 0) { 236 tp->t_state |= TS_WOPEN; 237 sleep((caddr_t) &tp->t_rawq, TTIPRI); 238 } 239 splx(priority); 240 241 return ((*linesw[tp->t_line].l_open)(device, tp)); 242 } 243 244 dmzparam(unit) 245 register int unit; 246 { 247 register struct tty *tp; 248 register struct dmzdevice *dmz_addr; 249 register int line_parameters; 250 register int octet; 251 int priority; 252 253 octet = OCTET(unit); 254 255 tp = &dmz_tty[unit]; 256 dmz_addr = (struct dmzdevice *)tp->t_addr; 257 258 priority = spl5(); 259 if ((tp->t_ispeed) == 0) { 260 tp->t_state |= TS_HUPCLS; 261 (void) dmzmctl(unit, DMZ_OFF, DMSET); 262 splx(priority); 263 return; 264 } 265 266 line_parameters = (dmz_speeds[tp->t_ospeed] << 12) | (dmz_speeds[tp->t_ispeed] << 8); 267 268 if ((tp->t_ispeed) == B134) 269 line_parameters |= DMZ_6BT | DMZ_PEN; 270 else if (tp->t_flags & (RAW | LITOUT | PASS8)) 271 line_parameters |= DMZ_8BT; 272 else 273 line_parameters |= DMZ_7BT | DMZ_PEN; 274 275 if (tp->t_flags & EVENP) 276 line_parameters |= DMZ_EPR; 277 if ((tp->t_ospeed) == B110) 278 line_parameters |= DMZ_SCD; 279 280 line_parameters |= (unit & 07); 281 282 dmz_addr->octet[octet].octet_lprm = line_parameters; 283 splx(priority); 284 } 285 286 /* ARGSUSED */ 287 dmzclose(device, flag) 288 dev_t device; 289 int flag; 290 { 291 register struct tty *tp; 292 register int unit; 293 294 unit = minor(device); 295 tp = &dmz_tty[unit]; 296 (*linesw[tp->t_line].l_close)(tp); 297 298 /* 299 * Clear break, hang-up and close the modem. 300 */ 301 (void) dmzmctl(unit, DMZ_BRK, DMBIC); 302 if (tp->t_state & TS_HUPCLS || (tp->t_state & TS_ISOPEN) == 0) 303 (void) dmzmctl(unit, DMZ_OFF, DMSET); 304 ttyclose(tp); 305 return; 306 } 307 308 dmzreset(uban) 309 int uban; 310 { 311 register int controller, unit; 312 register struct tty *tp; 313 register struct uba_device *ui; 314 register struct dmzdevice *dmz_addr; 315 int i; 316 int octet; 317 318 for (controller = 0; controller < NDMZ; controller++) { 319 ui = dmzinfo[controller]; 320 if (ui == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban) 321 continue; 322 printf("dmz%d ", controller); 323 dmz_addr = (struct dmzdevice *) ui->ui_addr; 324 325 if (dmz_ubinfo[uban]) { 326 dmz_ubinfo[uban] = uballoc(uban, (caddr_t)cfree, 327 nclist * sizeof(struct cblock), 0); 328 cbase[uban] = UBAI_ADDR(dmz_ubinfo[uban]); 329 } 330 331 for (octet = 0; octet < 3; octet++) 332 if ((dmzact[controller] & (1 << octet)) != 0) { 333 dmz_addr->octet[octet].octet_csr |= DMZ_IE; 334 dmz_addr->octet[octet].octet_receive.octet_sato = SILO_TIMEOUT; 335 } 336 337 unit = controller * 24; 338 339 /* 340 * If a unit is open or waiting for open to complete, 341 * reset it. 342 */ 343 for (i = 0; i < 24; i++) { 344 dmz_softc[unit].dmz_state = 0; 345 tp = &dmz_tty[unit]; 346 if (tp->t_state & (TS_ISOPEN | TS_WOPEN)) { 347 dmzparam(unit); 348 (void) dmzmctl(unit, DMZ_ON, DMSET); 349 tp->t_state &= ~TS_BUSY; 350 dmzstart(tp); 351 } 352 unit++; 353 } 354 } 355 return; 356 } 357 358 dmzread(device, uio) 359 dev_t device; 360 struct uio *uio; 361 { 362 register struct tty *tp; 363 int xstatus; 364 365 tp = &dmz_tty[minor(device)]; 366 xstatus = (*linesw[tp->t_line].l_read)(tp, uio); 367 return (xstatus); 368 } 369 370 dmzwrite(device, uio) 371 dev_t device; 372 struct uio *uio; 373 { 374 register struct tty *tp; 375 int xstatus; 376 377 tp = &dmz_tty[minor(device)]; 378 xstatus = (*linesw[tp->t_line].l_write)(tp, uio); 379 return (xstatus); 380 } 381 382 dmzrinta(controller) 383 int controller; 384 { 385 dmzrint(controller, 0); 386 } 387 388 dmzrintb(controller) 389 int controller; 390 { 391 dmzrint(controller, 1); 392 } 393 394 dmzrintc(controller) 395 int controller; 396 { 397 dmzrint(controller, 2); 398 } 399 400 dmzrint(controller, octet) 401 int controller; 402 register int octet; 403 { 404 register struct tty *tp; 405 register int character; 406 register struct dmzdevice *dmz_addr; 407 register struct tty *tp0; 408 register int unit; 409 register struct uba_device *ui; 410 int overrun; 411 412 overrun = 0; 413 ui = dmzinfo[controller]; 414 if (ui == 0 || ui->ui_alive == 0) 415 return; 416 dmz_addr = (struct dmzdevice *) ui->ui_addr; 417 tp0 = &dmz_tty[controller * 24]; 418 419 while ((character = dmz_addr->octet[octet].octet_receive.octet_rb) < 0) { 420 unit = (character >> 8) & 07; /* unit is bits 8-10 of rb */ 421 tp = tp0 + (octet * 8 + unit); 422 423 if (character & DMZ_DSC) { 424 dmz_addr->octet[octet].octet_csr = DMZ_IE | IR_RMSTSC | unit; 425 if (dmz_addr->octet[octet].octet_rmstsc & DMZ_CAR) 426 (void)(*linesw[tp->t_line].l_modem)(tp, 1); 427 else if ((dmzsoftCAR[controller] & 428 (1 << (octet * 8 + unit))) == 0 && 429 (*linesw[tp->t_line].l_modem)(tp, 0) == 0) 430 (void)dmzmctl(tp - dmz_tty, DMZ_OFF, DMSET); 431 continue; 432 } 433 434 if ((tp->t_state&TS_ISOPEN)==0) { 435 wakeup((caddr_t)&tp->t_rawq); 436 #ifdef PORTSELECTOR 437 if ((tp->t_state&TS_WOPEN) == 0) 438 #endif 439 continue; 440 } 441 442 if (character & DMZ_PE) { 443 if ((tp->t_flags & (EVENP | ODDP)) == EVENP || 444 (tp->t_flags & (EVENP | ODDP)) == ODDP) 445 continue; 446 } 447 448 if ((character & DMZ_DO) && overrun == 0) { 449 log(LOG_WARNING, "dmz%d: silo overflow\n", controller); 450 overrun = 1; 451 } 452 453 if (character & DMZ_FE) { 454 if (tp->t_flags & RAW) 455 character = 0; 456 else 457 character = tp->t_intrc; 458 } 459 460 (*linesw[tp->t_line].l_rint)(character, tp); 461 } 462 463 return; 464 } 465 466 dmzxinta(controller) 467 int controller; 468 { 469 dmzxint(controller, 0); 470 } 471 472 dmzxintb(controller) 473 int controller; 474 { 475 dmzxint(controller, 1); 476 } 477 478 dmzxintc(controller) 479 int controller; 480 { 481 dmzxint(controller, 2); 482 } 483 484 dmzxint(controller, octet) 485 int controller; 486 register int octet; 487 { 488 register struct tty *tp; 489 register struct dmzdevice *dmz_addr; 490 register struct uba_device *ui; 491 register int unit, t; 492 int priority; 493 494 ui = dmzinfo[controller]; 495 dmz_addr = (struct dmzdevice *)ui->ui_addr; 496 497 priority = spl5(); 498 499 while ((t = dmz_addr->octet[octet].octet_csr) & DMZ_TRDY) { 500 unit = controller * 24 + (octet * 8 + ((t>>8) & 07)); 501 tp = &dmz_tty[unit]; 502 tp->t_state &= ~TS_BUSY; 503 504 if (t & DMZ_NXM) 505 printf("dmz%d: NXM line %d\n", controller, 506 octet * 8 + (unit & 07)); 507 508 if (tp->t_state & TS_FLUSH) { 509 tp->t_state &= ~TS_FLUSH; 510 dmz_addr->octet[octet].octet_csr = 511 DMZ_IE | IR_LCTMR | (unit & 07); 512 dmz_addr->octet[octet].octet_lctmr = 513 (dmz_addr->octet[octet].octet_lctmr | DMZ_TE); 514 } else 515 if (dmz_softc[unit].dmz_state & ST_DMA) 516 ndflush(&tp->t_outq, dmz_softc[unit].dmz_count); 517 dmz_softc[unit].dmz_state = 0; 518 519 if (tp->t_line) 520 (*linesw[tp->t_line].l_start)(tp); 521 else 522 dmzstart(tp); 523 } 524 525 splx(priority); 526 return; 527 } 528 529 dmzstart(tp) 530 register struct tty *tp; 531 { 532 register struct dmzdevice *dmz_addr; 533 register int unit, nch, room; 534 int controller, octet; 535 int priority, car, use_dma; 536 register int i; 537 register char *cp; 538 539 unit = minor(tp->t_dev); 540 controller = DMZ(unit); 541 octet = OCTET(unit); 542 dmz_addr = (struct dmzdevice *)tp->t_addr; 543 544 priority = spl5(); 545 546 if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP)) 547 goto out; 548 549 /* 550 * If the transmitter has been disabled, reenable it. 551 * If the transmitter was disabled before the xint (the 552 * ST_INBUSY was still on), then reset the BUSY state and 553 * we will wait for the interrupt. If !TS_BUSY, we already 554 * saw the interrupt so we can start another transmission. 555 */ 556 if (dmz_softc[unit].dmz_state & ST_TXOFF) { 557 dmz_addr->octet[octet].octet_csr = 558 DMZ_IE | IR_LCTMR | (unit & 07); 559 dmz_addr->octet[octet].octet_lctmr = 560 (dmz_addr->octet[octet].octet_lctmr | DMZ_TE); 561 dmz_softc[unit].dmz_state &= ~ST_TXOFF; 562 if (dmz_softc[unit].dmz_state & ST_INBUSY) { 563 dmz_softc[unit].dmz_state &= ~ST_INBUSY; 564 tp->t_state |= TS_BUSY; 565 goto out; 566 } 567 } 568 569 if (tp->t_outq.c_cc <= TTLOWAT(tp)) { 570 if (tp->t_state & TS_ASLEEP) { 571 tp->t_state &= ~TS_ASLEEP; 572 wakeup((caddr_t)&tp->t_outq); 573 } 574 if (tp->t_wsel) { 575 selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); 576 tp->t_wsel = 0; 577 tp->t_state &= ~TS_WCOLL; 578 } 579 } 580 581 if (tp->t_outq.c_cc == 0) 582 goto out; 583 if (tp->t_flags & (RAW | LITOUT)) 584 nch = ndqb(&tp->t_outq, 0); 585 else { 586 nch = ndqb(&tp->t_outq, 0200); 587 if (nch == 0) { 588 nch = getc(&tp->t_outq); 589 timeout(ttrstrt, (caddr_t)tp, (nch & 0x7f)+6); 590 tp->t_state |= TS_TIMEOUT; 591 goto out; 592 } 593 } 594 595 /* 596 * Should we use DMA or SILO mode? 597 * If nch is greater than DO_DMA_COUNT then DMA. 598 */ 599 if (nch) { 600 dmz_addr->octet[octet].octet_csr = 601 DMZ_IE | IR_LCTMR | (unit & 07); 602 dmz_addr->octet[octet].octet_lctmr = 603 (dmz_addr->octet[octet].octet_lctmr | DMZ_TE); 604 tp->t_state |= TS_BUSY; 605 606 use_dma = FALSE; 607 room = DMZ_SIZ; 608 609 if (nch > DO_DMA_COUNT) 610 use_dma = TRUE; 611 612 if (use_dma && dmz_dma_on) { 613 car = UBACVT(tp->t_outq.c_cf, 614 dmzinfo[controller]->ui_ubanum); 615 dmz_softc[unit].dmz_count = nch; 616 dmz_softc[unit].dmz_state |= ST_DMA; 617 dmz_addr->octet[octet].octet_csr = 618 DMZ_IE | IR_TBA | (unit & 07); 619 dmz_addr->octet[octet].octet_tba = car; 620 dmz_addr->octet[octet].octet_tcc = 621 ((car >> 2) & 0xc000) | nch; 622 } else { 623 dmz_softc[unit].dmz_state &= ~ST_DMA; 624 cp = tp->t_outq.c_cf; 625 nch = MIN(nch, room); 626 dmz_addr->octet[octet].octet_csr = 627 DMZ_IE | IR_TBUF | (unit & 07); 628 for (i = 0; i < nch; i++) 629 dmz_addr->octet[octet].octet_tbf = *cp++ ; 630 ndflush(&tp->t_outq, nch); 631 } 632 } 633 634 out: 635 splx(priority); 636 return; 637 } 638 639 /* ARGSUSED */ 640 dmzstop(tp, flag) 641 register struct tty *tp; 642 { 643 register struct dmzdevice *dmz_addr; 644 register int unit, priority, octet; 645 646 priority = spl5(); 647 dmz_addr = (struct dmzdevice *) tp->t_addr; 648 unit = minor(tp->t_dev); 649 octet = OCTET(unit); 650 651 dmz_addr->octet[octet].octet_csr = IR_LCTMR | (unit & 07) | DMZ_IE; 652 dmz_addr->octet[octet].octet_lctmr = 653 (dmz_addr->octet[octet].octet_lctmr & ~DMZ_TE); 654 dmz_softc[unit].dmz_state |= ST_TXOFF; 655 if ((tp->t_state & TS_TTSTOP) == 0) { 656 tp->t_state |= (TS_FLUSH | TS_BUSY); 657 dmz_addr->octet[octet].octet_lctmr = 658 (dmz_addr->octet[octet].octet_lctmr | DMZ_FLS); 659 } else if (tp->t_state & TS_BUSY) { 660 dmz_softc[unit].dmz_state |= ST_INBUSY; 661 tp->t_state &= ~TS_BUSY; 662 } 663 664 splx(priority); 665 return; 666 } 667 668 /* ARGSUSED */ 669 dmzioctl(device, command, data, flag) 670 dev_t device; 671 caddr_t data; 672 { 673 register struct tty *tp; 674 register int unit; 675 int error; 676 677 unit = minor(device); 678 tp = &dmz_tty[unit]; 679 680 error = (*linesw[tp->t_line].l_ioctl)(tp, command, data, flag); 681 if (error >= 0) 682 return (error); 683 error = ttioctl(tp, command, data, flag); 684 if (error >= 0) { 685 if (command == TIOCSETP || command == TIOCSETN || 686 command == TIOCLSET || command == TIOCLBIS || 687 command == TIOCLBIC) 688 dmzparam(unit); 689 return (error); 690 } 691 692 switch (command) { 693 case TIOCSBRK: 694 (void) dmzmctl(unit, DMZ_BRK, DMBIS); 695 break; 696 case TIOCCBRK: 697 (void) dmzmctl(unit, DMZ_BRK, DMBIC); 698 break; 699 case TIOCSDTR: 700 (void) dmzmctl(unit, DMZ_DTR | DMZ_RTS, DMBIS); 701 break; 702 case TIOCCDTR: 703 (void) dmzmctl(unit, DMZ_DTR | DMZ_RTS, DMBIC); 704 break; 705 case TIOCMSET: 706 (void) dmzmctl(unit, dmtodmz(*(int *)data), DMSET); 707 break; 708 case TIOCMBIS: 709 (void) dmzmctl(unit, dmtodmz(*(int *)data), DMBIS); 710 break; 711 case TIOCMBIC: 712 (void) dmzmctl(unit, dmtodmz(*(int *)data), DMBIC); 713 break; 714 case TIOCMGET: 715 *(int *)data = dmzmctl(unit, 0, DMGET); 716 break; 717 default: 718 return (ENOTTY); 719 } 720 return (0); 721 } 722 723 dmzmctl(unit, bits, how) 724 register int unit; 725 int bits, how; 726 { 727 register struct dmzdevice *dmz_addr; 728 register int modem_status, line_control; 729 int priority; 730 int octet; 731 732 octet = OCTET(unit); 733 dmz_addr = (struct dmzdevice *) dmzinfo[DMZ(unit)]->ui_addr; 734 735 priority = spl5(); 736 dmz_addr->octet[octet].octet_csr = DMZ_IE | IR_RMSTSC | (unit & 07); 737 modem_status = dmz_addr->octet[octet].octet_rmstsc & 0xff00; 738 739 dmz_addr->octet[octet].octet_csr = DMZ_IE | IR_LCTMR | (unit & 07); 740 line_control = dmz_addr->octet[octet].octet_lctmr; 741 742 743 switch (how) { 744 case DMSET: 745 line_control = bits; 746 break; 747 case DMBIS: 748 line_control |= bits; 749 break; 750 case DMBIC: 751 line_control &= ~bits; 752 break; 753 case DMGET: 754 (void) splx(priority); 755 return (dmztodm(modem_status, line_control)); 756 } 757 758 dmz_addr->octet[octet].octet_csr = 759 DMZ_IE | IR_LCTMR | (unit & 07); 760 dmz_addr->octet[octet].octet_lctmr = line_control; 761 762 splx(priority); 763 return (modem_status); 764 } 765 766 /* 767 * Routine to convert modem status from dm to dmz lctmr format. 768 */ 769 dmtodmz(bits) 770 register int bits; 771 { 772 register int lcr = DMZ_LCE; 773 774 if (bits & DML_DTR) 775 lcr |= DMZ_DTR; 776 if (bits & DML_RTS) 777 lcr |= DMZ_RTS; 778 if (bits & DML_ST) 779 lcr |= DMF_ST; 780 if (bits & DML_USR) 781 lcr |= DMZ_USRW; 782 return (lcr); 783 } 784 785 /* 786 * Routine to convert modem status from dmz receive modem status 787 * and line control register to dm format. 788 * If dmz user modem read bit set, set DML_USR. 789 */ 790 dmztodm(rms, lcr) 791 register int rms, lcr; 792 { 793 794 rms = ((rms & (DMZ_DSR|DMZ_RNG|DMZ_CAR|DMZ_CTS|DMF_SR)) >> 7) | 795 ((rms & DMZ_USRR) >> 1) | DML_LE; 796 if (lcr & DMZ_DTR) 797 rms |= DML_DTR; 798 if (lcr & DMF_ST) 799 rms |= DML_ST; 800 if (lcr & DMZ_RTS) 801 rms |= DML_RTS; 802 return (rms); 803 } 804 #endif 805