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