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