1: /* 2: * Copyright (c) 1985, 1986 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 7.1 (Berkeley) 6/5/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