|
|
1.1 ! root 1: /* ! 2: * Mach Operating System ! 3: * Copyright (c) 1994,1993,1991,1990 Carnegie Mellon University ! 4: * All Rights Reserved. ! 5: * ! 6: * Permission to use, copy, modify and distribute this software and its ! 7: * documentation is hereby granted, provided that both the copyright ! 8: * notice and this permission notice appear in all copies of the ! 9: * software, derivative works or modified versions, and any portions ! 10: * thereof, and that both notices appear in supporting documentation. ! 11: * ! 12: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" ! 13: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR ! 14: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. ! 15: * ! 16: * Carnegie Mellon requests users of this software to return to ! 17: * ! 18: * Software Distribution Coordinator or [email protected] ! 19: * School of Computer Science ! 20: * Carnegie Mellon University ! 21: * Pittsburgh PA 15213-3890 ! 22: * ! 23: * any improvements or extensions that they make and grant Carnegie Mellon ! 24: * the rights to redistribute these changes. ! 25: */ ! 26: ! 27: #include <com.h> ! 28: #if NCOM > 0 ! 29: ! 30: #include <mach/std_types.h> ! 31: #include <sys/types.h> ! 32: #include <sys/time.h> ! 33: #include <device/conf.h> ! 34: #include <device/errno.h> ! 35: #include <device/tty.h> ! 36: #include <device/io_req.h> ! 37: ! 38: #include <i386/ipl.h> ! 39: #include <i386/pio.h> ! 40: #include <i386/machspl.h> ! 41: #include <chips/busses.h> ! 42: #include <i386at/comreg.h> ! 43: ! 44: #include <rc.h> ! 45: #include <cons.h> ! 46: ! 47: extern void timeout(), ttrstrt(); ! 48: ! 49: int comprobe(), comintr(), comstart(), commctl(); ! 50: void comattach(); ! 51: static void comparam(); ! 52: int comstop(), comgetstat(), comsetstat(); ! 53: ! 54: static vm_offset_t com_std[NCOM] = { 0 }; ! 55: struct bus_device *cominfo[NCOM]; ! 56: struct bus_driver comdriver = { ! 57: comprobe, 0, comattach, 0, com_std, "com", cominfo, 0, 0, 0}; ! 58: ! 59: struct tty com_tty[NCOM]; ! 60: int commodem[NCOM]; ! 61: int comcarrier[NCOM] = {0, 0,}; ! 62: boolean_t comfifo[NCOM]; ! 63: boolean_t comtimer_active; ! 64: int comtimer_state[NCOM]; ! 65: ! 66: #if RCLINE >= 0 ! 67: #define RCBAUD B9600 ! 68: static struct bus_device *comcndev; ! 69: int comcnprobe(struct consdev *cp); ! 70: int comcninit(struct consdev *cp); ! 71: int comcngetc(dev_t dev, int wait); ! 72: int comcnputc(dev_t dev, int c); ! 73: #endif ! 74: ! 75: #ifndef PORTSELECTOR ! 76: #define ISPEED B9600 ! 77: #define IFLAGS (EVENP|ODDP|ECHO|CRMOD) ! 78: #else ! 79: #define ISPEED B4800 ! 80: #define IFLAGS (EVENP|ODDP) ! 81: #endif ! 82: ! 83: u_short divisorreg[] = { ! 84: 0, 2304, 1536, 1047, /* 0, 50, 75, 110*/ ! 85: 857, 768, 576, 384, 192, /* 134.5, 150, 200, 300, 600*/ ! 86: 96, 64, 48, /* 1200, 1800, 2000, 2400 */ ! 87: 24, 12, /* 3600, 4800, 7200, 9600 */ ! 88: 6, 3, 2}; /* 19200, 38400, 56000 */ ! 89: ! 90: ! 91: /* ! 92: * ! 93: * Probes are called during kernel boot: return 1 to mean that ! 94: * the relevant device is present today. ! 95: * ! 96: */ ! 97: int ! 98: comprobe_general(struct bus_device *dev, int noisy) ! 99: { ! 100: u_short addr = dev->address; ! 101: int unit = dev->unit; ! 102: int oldctl, oldmsb; ! 103: char *type = "8250"; ! 104: int i; ! 105: ! 106: if ((unit < 0) || (unit > NCOM)) { ! 107: printf("com %d out of range\n", unit); ! 108: return(0); ! 109: } ! 110: oldctl = inb(LINE_CTL(addr)); /* Save old value of LINE_CTL */ ! 111: oldmsb = inb(BAUD_MSB(addr)); /* Save old value of BAUD_MSB */ ! 112: outb(LINE_CTL(addr), 0); /* Select INTR_ENAB */ ! 113: outb(BAUD_MSB(addr), 0); ! 114: if (inb(BAUD_MSB(addr)) != 0) ! 115: { ! 116: outb(LINE_CTL(addr), oldctl); ! 117: outb(BAUD_MSB(addr), oldmsb); ! 118: return 0; ! 119: } ! 120: outb(LINE_CTL(addr), iDLAB); /* Select BAUD_MSB */ ! 121: outb(BAUD_MSB(addr), 255); ! 122: if (inb(BAUD_MSB(addr)) != 255) ! 123: { ! 124: outb(LINE_CTL(addr), oldctl); ! 125: outb(BAUD_MSB(addr), oldmsb); ! 126: return 0; ! 127: } ! 128: outb(LINE_CTL(addr), 0); /* Select INTR_ENAB */ ! 129: if (inb(BAUD_MSB(addr)) != 0) /* Check that it has kept its value*/ ! 130: { ! 131: outb(LINE_CTL(addr), oldctl); ! 132: outb(BAUD_MSB(addr), oldmsb); ! 133: return 0; ! 134: } ! 135: ! 136: /* Com port found, now check what chip it has */ ! 137: ! 138: for(i = 0; i < 256; i++) /* Is there Scratch register */ ! 139: { ! 140: outb(SCR(addr), i); ! 141: if (inb(SCR(addr)) != i) ! 142: break; ! 143: } ! 144: if (i == 256) ! 145: { /* Yes == 450 or 460 */ ! 146: outb(SCR(addr), 0); ! 147: type = "82450 or 16450"; ! 148: outb(FIFO_CTL(addr), iFIFOENA | iFIFO14CH); /* Enable fifo */ ! 149: if ((inb(FIFO_CTL(addr)) & iFIFO14CH) != 0) ! 150: { /* Was it successfull */ ! 151: /* if both bits are not set then broken xx550 */ ! 152: if ((inb(FIFO_CTL(addr)) & iFIFO14CH) == iFIFO14CH) ! 153: { ! 154: type = "82550 or 16550"; ! 155: comfifo[unit] = TRUE; ! 156: } ! 157: else ! 158: { ! 159: type = "82550 or 16550 with non-working FIFO"; ! 160: } ! 161: outb(INTR_ID(addr), 0x00); /* Disable fifos */ ! 162: } ! 163: } ! 164: if (noisy) ! 165: printf("com%d: %s chip.\n", unit, type); ! 166: return 1; ! 167: } ! 168: ! 169: /* ! 170: * Probe routine for use during kernel startup when it is probing ! 171: * all of bus_device_init ! 172: */ ! 173: int ! 174: comprobe(int port, struct bus_device *dev) ! 175: { ! 176: return comprobe_general(dev, /*noisy*/ 0); ! 177: } ! 178: ! 179: #if RCLINE >= 0 ! 180: /* ! 181: * Probe routine for use by the console ! 182: */ ! 183: int ! 184: comcnprobe(struct consdev *cp) ! 185: { ! 186: struct bus_device *b; ! 187: int maj, unit, pri; ! 188: ! 189: maj = 0; ! 190: unit = -1; ! 191: pri = CN_DEAD; ! 192: ! 193: for (b = bus_device_init; b->driver; b++) ! 194: if (strcmp(b->name, "com") == 0 ! 195: && b->unit == RCLINE ! 196: && comprobe_general(b, /*quiet*/ 0)) ! 197: { ! 198: /* Found one */ ! 199: comcndev = b; ! 200: unit = b->unit; ! 201: pri = CN_REMOTE; ! 202: break; ! 203: } ! 204: ! 205: cp->cn_dev = makedev(maj, unit); ! 206: cp->cn_pri = pri; ! 207: } ! 208: #endif ! 209: ! 210: ! 211: /* ! 212: * ! 213: * Device Attach's are called during kernel boot, but only if the matching ! 214: * device Probe returned a 1. ! 215: * ! 216: */ ! 217: void ! 218: comattach(struct bus_device *dev) ! 219: { ! 220: u_char unit = dev->unit; ! 221: u_short addr = dev->address; ! 222: ! 223: take_dev_irq(dev); ! 224: printf(", port = %x, spl = %d, pic = %d. (DOS COM%d)", ! 225: dev->address, dev->sysdep, dev->sysdep1, unit+1); ! 226: ! 227: /* comcarrier[unit] = addr->flags;*/ ! 228: commodem[unit] = 0; ! 229: ! 230: outb(INTR_ENAB(addr), 0); ! 231: outb(MODEM_CTL(addr), 0); ! 232: while (!(inb(INTR_ID(addr))&1)) { ! 233: (void) inb(LINE_STAT (addr)); /* reset overrun error etc */ ! 234: (void) inb(TXRX (addr)); /* reset data-ready */ ! 235: (void) inb(MODEM_STAT(addr)); /* reset modem status reg */ ! 236: } ! 237: } ! 238: ! 239: #if RCLINE >= 0 ! 240: /* ! 241: * Attach/init routine for console. This isn't called by ! 242: * configure_bus_device which sets the alive, adaptor, and minfo ! 243: * fields of the bus_device struct (comattach is), therefore we do ! 244: * that by hand. ! 245: */ ! 246: int ! 247: comcninit(struct consdev *cp) ! 248: { ! 249: u_char unit = comcndev->unit; ! 250: u_short addr = comcndev->address; ! 251: ! 252: take_dev_irq(comcndev); ! 253: ! 254: comcndev->alive = 1; ! 255: comcndev->adaptor = 0; ! 256: cominfo[minor(cp->cn_dev)] = comcndev; ! 257: ! 258: outb(LINE_CTL(addr), iDLAB); ! 259: outb(BAUD_LSB(addr), divisorreg[RCBAUD] & 0xff); ! 260: outb(BAUD_MSB(addr), divisorreg[RCBAUD] >>8); ! 261: outb(LINE_CTL(addr), i7BITS|iPEN); ! 262: outb(INTR_ENAB(addr), 0); ! 263: outb(MODEM_CTL(addr), iDTR|iRTS|iOUT2); ! 264: ! 265: { ! 266: char msg[128]; ! 267: volatile unsigned char *p = (volatile unsigned char *)0xb8000; ! 268: int i; ! 269: ! 270: sprintf(msg, " **** using COM port %d for console ****", ! 271: unit+1); ! 272: for (i = 0; msg[i]; i++) { ! 273: p[2*i] = msg[i]; ! 274: p[2*i+1] = (0<<7) /* blink */ ! 275: | (0x0<<4) /* bg */ ! 276: | (1<<3) /* hi-intensity */ ! 277: | 0x4; /* fg */ ! 278: } ! 279: } ! 280: ! 281: } ! 282: #endif ! 283: ! 284: /* ! 285: * Probe for COM<dev> after autoconfiguration. ! 286: * Used to handle PCMCIA modems, which may appear ! 287: * at any time. ! 288: */ ! 289: boolean_t com_reprobe( ! 290: int unit) ! 291: { ! 292: struct bus_device *device; ! 293: ! 294: /* ! 295: * Look for COM device <unit> in the device ! 296: * initialization list. It must not be alive ! 297: * (otherwise we would have opened it already). ! 298: */ ! 299: for (device = bus_device_init; device->driver; device++) { ! 300: if (device->driver == &comdriver && device->unit == unit && ! 301: !device->alive && device->ctlr == (char)-1) ! 302: { ! 303: /* ! 304: * Found an entry for com port <unit>. ! 305: * Probe it. ! 306: */ ! 307: if (configure_bus_device(device->name, ! 308: device->address, ! 309: device->phys_address, ! 310: 0, ! 311: "atbus")) ! 312: return TRUE; ! 313: } ! 314: } ! 315: return FALSE; ! 316: } ! 317: ! 318: io_return_t comopen( ! 319: int dev, ! 320: int flag, ! 321: io_req_t ior) ! 322: { ! 323: int unit = minor(dev); ! 324: u_short addr; ! 325: struct bus_device *isai; ! 326: struct tty *tp; ! 327: spl_t s; ! 328: io_return_t result; ! 329: ! 330: if (unit >= NCOM) ! 331: return ENXIO; /* no such device */ ! 332: if ((isai = cominfo[unit]) == 0 || isai->alive == 0) { ! 333: /* ! 334: * Try to probe it again ! 335: */ ! 336: if (!com_reprobe(unit)) ! 337: return ENXIO; ! 338: } ! 339: tp = &com_tty[unit]; ! 340: ! 341: if ((tp->t_state & (TS_ISOPEN|TS_WOPEN)) == 0) { ! 342: ttychars(tp); ! 343: tp->t_addr = (char *)isai->address; ! 344: tp->t_dev = dev; ! 345: tp->t_oproc = comstart; ! 346: tp->t_stop = comstop; ! 347: tp->t_mctl = commctl; ! 348: tp->t_getstat = comgetstat; ! 349: tp->t_setstat = comsetstat; ! 350: #ifndef PORTSELECTOR ! 351: if (tp->t_ispeed == 0) { ! 352: #else ! 353: tp->t_state |= TS_HUPCLS; ! 354: #endif /* PORTSELECTOR */ ! 355: tp->t_ispeed = ISPEED; ! 356: tp->t_ospeed = ISPEED; ! 357: tp->t_flags = IFLAGS; ! 358: tp->t_state &= ~TS_BUSY; ! 359: #ifndef PORTSELECTOR ! 360: } ! 361: #endif /* PORTSELECTOR */ ! 362: } ! 363: /*rvb tp->t_state |= TS_WOPEN; */ ! 364: if ((tp->t_state & TS_ISOPEN) == 0) ! 365: comparam(unit); ! 366: addr = (int)tp->t_addr; ! 367: ! 368: s = spltty(); ! 369: if (!comcarrier[unit]) /* not originating */ ! 370: tp->t_state |= TS_CARR_ON; ! 371: else { ! 372: int modem_stat = inb(MODEM_STAT(addr)); ! 373: if (modem_stat & iRLSD) ! 374: tp->t_state |= TS_CARR_ON; ! 375: else ! 376: tp->t_state &= ~TS_CARR_ON; ! 377: fix_modem_state(unit, modem_stat); ! 378: } ! 379: splx(s); ! 380: ! 381: result = char_open(dev, tp, flag, ior); ! 382: ! 383: if (!comtimer_active) { ! 384: comtimer_active = TRUE; ! 385: comtimer(); ! 386: } ! 387: ! 388: s = spltty(); ! 389: while(!(inb(INTR_ID(addr))&1)) { /* while pending interrupts */ ! 390: (void) inb(LINE_STAT (addr)); /* reset overrun error */ ! 391: (void) inb(TXRX (addr)); /* reset data-ready */ ! 392: (void) inb(MODEM_STAT(addr)); /* reset modem status */ ! 393: } ! 394: splx(s); ! 395: return result; ! 396: } ! 397: ! 398: io_return_t comclose(dev, flag) ! 399: int dev; ! 400: int flag; ! 401: { ! 402: struct tty *tp = &com_tty[minor(dev)]; ! 403: u_short addr = (int)tp->t_addr; ! 404: ! 405: ttyclose(tp); ! 406: if (tp->t_state&TS_HUPCLS || (tp->t_state&TS_ISOPEN)==0) { ! 407: outb(INTR_ENAB(addr), 0); ! 408: outb(MODEM_CTL(addr), 0); ! 409: tp->t_state &= ~TS_BUSY; ! 410: commodem[minor(dev)] = 0; ! 411: if (comfifo[minor(dev)] != 0) ! 412: outb(INTR_ID(addr), 0x00); /* Disable fifos */ ! 413: } ! 414: return 0; ! 415: } ! 416: ! 417: io_return_t comread(dev, ior) ! 418: int dev; ! 419: io_req_t ior; ! 420: { ! 421: return char_read(&com_tty[minor(dev)], ior); ! 422: } ! 423: ! 424: io_return_t comwrite(dev, ior) ! 425: int dev; ! 426: io_req_t ior; ! 427: { ! 428: return char_write(&com_tty[minor(dev)], ior); ! 429: } ! 430: ! 431: io_return_t comportdeath(dev, port) ! 432: dev_t dev; ! 433: mach_port_t port; ! 434: { ! 435: return (tty_portdeath(&com_tty[minor(dev)], port)); ! 436: } ! 437: ! 438: io_return_t ! 439: comgetstat(dev, flavor, data, count) ! 440: dev_t dev; ! 441: int flavor; ! 442: int *data; /* pointer to OUT array */ ! 443: unsigned int *count; /* out */ ! 444: { ! 445: io_return_t result = D_SUCCESS; ! 446: int unit = minor(dev); ! 447: ! 448: switch (flavor) { ! 449: case TTY_MODEM: ! 450: fix_modem_state(unit, inb(MODEM_STAT(cominfo[unit]->address))); ! 451: *data = commodem[unit]; ! 452: *count = 1; ! 453: break; ! 454: default: ! 455: result = tty_get_status(&com_tty[unit], flavor, data, count); ! 456: break; ! 457: } ! 458: return (result); ! 459: } ! 460: ! 461: io_return_t ! 462: comsetstat(dev, flavor, data, count) ! 463: dev_t dev; ! 464: int flavor; ! 465: int * data; ! 466: unsigned int count; ! 467: { ! 468: io_return_t result = D_SUCCESS; ! 469: int unit = minor(dev); ! 470: struct tty *tp = &com_tty[unit]; ! 471: ! 472: switch (flavor) { ! 473: case TTY_SET_BREAK: ! 474: commctl(tp, TM_BRK, DMBIS); ! 475: break; ! 476: case TTY_CLEAR_BREAK: ! 477: commctl(tp, TM_BRK, DMBIC); ! 478: break; ! 479: case TTY_MODEM: ! 480: commctl(tp, *data, DMSET); ! 481: break; ! 482: default: ! 483: result = tty_set_status(&com_tty[unit], flavor, data, count); ! 484: if (result == D_SUCCESS && flavor == TTY_STATUS) ! 485: comparam(unit); ! 486: return (result); ! 487: } ! 488: return (D_SUCCESS); ! 489: } ! 490: ! 491: comintr(unit) ! 492: int unit; ! 493: { ! 494: register struct tty *tp = &com_tty[unit]; ! 495: u_short addr = cominfo[unit]->address; ! 496: static char comoverrun = 0; ! 497: char c, line, intr_id; ! 498: int line_stat; ! 499: ! 500: while (! ((intr_id=(inb(INTR_ID(addr))&MASKi)) & 1)) ! 501: switch (intr_id) { ! 502: case MODi: ! 503: /* modem change */ ! 504: commodem_intr(unit, inb(MODEM_STAT(addr))); ! 505: break; ! 506: ! 507: case TRAi: ! 508: comtimer_state[unit] = 0; ! 509: tp->t_state &= ~(TS_BUSY|TS_FLUSH); ! 510: tt_write_wakeup(tp); ! 511: (void) comstart(tp); ! 512: break; ! 513: case RECi: ! 514: case CTIi: /* Character timeout indication */ ! 515: if (tp->t_state&TS_ISOPEN) { ! 516: while ((line = inb(LINE_STAT(addr))) & iDR) { ! 517: c = inb(TXRX(addr)); ! 518: ttyinput(c, tp); ! 519: } ! 520: } else ! 521: tt_open_wakeup(tp); ! 522: break; ! 523: case LINi: ! 524: line_stat = inb(LINE_STAT(addr)); ! 525: ! 526: if ((line_stat & iPE) && ! 527: ((tp->t_flags&(EVENP|ODDP)) == EVENP || ! 528: (tp->t_flags&(EVENP|ODDP)) == ODDP)) { ! 529: /* parity error */; ! 530: } else if (line&iOR && !comoverrun) { ! 531: printf("com%d: overrun\n", unit); ! 532: comoverrun = 1; ! 533: } else if (line_stat & (iFE | iBRKINTR)) { ! 534: /* framing error or break */ ! 535: ttyinput(tp->t_breakc, tp); ! 536: } ! 537: break; ! 538: } ! 539: } ! 540: ! 541: static void ! 542: comparam(unit) ! 543: register int unit; ! 544: { ! 545: struct tty *tp = &com_tty[unit]; ! 546: u_short addr = (int)tp->t_addr; ! 547: spl_t s = spltty(); ! 548: int mode; ! 549: ! 550: if (tp->t_ispeed == B0) { ! 551: tp->t_state |= TS_HUPCLS; ! 552: outb(MODEM_CTL(addr), iOUT2); ! 553: commodem[unit] = 0; ! 554: splx(s); ! 555: return; ! 556: } ! 557: ! 558: /* Do input buffering */ ! 559: if (tp->t_ispeed >= B300) ! 560: tp->t_state |= TS_MIN; ! 561: ! 562: outb(LINE_CTL(addr), iDLAB); ! 563: outb(BAUD_LSB(addr), divisorreg[tp->t_ispeed] & 0xff); ! 564: outb(BAUD_MSB(addr), divisorreg[tp->t_ispeed] >> 8); ! 565: ! 566: if (tp->t_flags & (RAW|LITOUT|PASS8)) ! 567: mode = i8BITS; ! 568: else ! 569: mode = i7BITS | iPEN; ! 570: if (tp->t_flags & EVENP) ! 571: mode |= iEPS; ! 572: if (tp->t_ispeed == B110) ! 573: /* ! 574: * 110 baud uses two stop bits - ! 575: * all other speeds use one ! 576: */ ! 577: mode |= iSTB; ! 578: ! 579: outb(LINE_CTL(addr), mode); ! 580: ! 581: outb(INTR_ENAB(addr), iTX_ENAB|iRX_ENAB|iMODEM_ENAB|iERROR_ENAB); ! 582: if (comfifo[unit]) ! 583: outb(FIFO_CTL(addr), iFIFOENA|iFIFO14CH); ! 584: outb(MODEM_CTL(addr), iDTR|iRTS|iOUT2); ! 585: commodem[unit] |= (TM_DTR|TM_RTS); ! 586: splx(s); ! 587: } ! 588: ! 589: comparm(int unit, int baud, int intr, int mode, int modem) ! 590: { ! 591: u_short addr = (u_short)(cominfo[unit]->address); ! 592: spl_t s = spltty(); ! 593: ! 594: if (unit != 0 && unit != 1) { ! 595: printf("comparm(unit, baud, mode, intr, modem)\n"); ! 596: splx(s); ! 597: return; ! 598: } ! 599: outb(LINE_CTL(addr), iDLAB); ! 600: outb(BAUD_LSB(addr), divisorreg[baud] & 0xff); ! 601: outb(BAUD_MSB(addr), divisorreg[baud] >> 8); ! 602: outb(LINE_CTL(addr), mode); ! 603: outb(INTR_ENAB(addr), intr); ! 604: outb(MODEM_CTL(addr), modem); ! 605: splx(s); ! 606: } ! 607: ! 608: int comst_1, comst_2, comst_3, comst_4, comst_5 = 14; ! 609: ! 610: int ! 611: comstart(tp) ! 612: struct tty *tp; ! 613: { ! 614: char nch; ! 615: int i; ! 616: ! 617: if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP|TS_BUSY)) { ! 618: comst_1++; ! 619: return(0); ! 620: } ! 621: if ((!queue_empty(&tp->t_delayed_write)) && ! 622: (tp->t_outq.c_cc <= TTLOWAT(tp))) { ! 623: comst_2++; ! 624: tt_write_wakeup(tp); ! 625: } ! 626: if (!tp->t_outq.c_cc) { ! 627: comst_3++; ! 628: return(0); ! 629: } ! 630: ! 631: #if 0 ! 632: i = (comfifo[minor(tp->t_dev)]) ? /*14*/comst_5 : 1; ! 633: ! 634: tp->t_state |= TS_BUSY; ! 635: while (i-- > 0) { ! 636: nch = getc(&tp->t_outq); ! 637: if (nch == -1) break; ! 638: if ((nch & 0200) && ((tp->t_flags & LITOUT) == 0)) { ! 639: timeout(ttrstrt, (char *)tp, (nch & 0x7f) + 6); ! 640: tp->t_state |= TS_TIMEOUT; ! 641: comst_4++; ! 642: return(0); ! 643: } ! 644: outb(TXRX((int)tp->t_addr), nch); ! 645: } ! 646: #else ! 647: nch = getc(&tp->t_outq); ! 648: if ((nch & 0200) && ((tp->t_flags & LITOUT) == 0)) { ! 649: timeout(ttrstrt, (char *)tp, (nch & 0x7f) + 6); ! 650: tp->t_state |= TS_TIMEOUT; ! 651: comst_4++; ! 652: return(0); ! 653: } ! 654: outb(TXRX((int)tp->t_addr), nch); ! 655: tp->t_state |= TS_BUSY; ! 656: #endif ! 657: return(0); ! 658: } ! 659: ! 660: /* Check for stuck xmitters */ ! 661: int comtimer_interval = 5; ! 662: ! 663: comtimer() ! 664: { ! 665: spl_t s = spltty(); ! 666: struct tty *tp = com_tty; ! 667: int i, nch; ! 668: ! 669: for (i = 0; i < NCOM; i++, tp++) { ! 670: if ((tp->t_state & TS_ISOPEN) == 0) ! 671: continue; ! 672: if (!tp->t_outq.c_cc) ! 673: continue; ! 674: if (++comtimer_state[i] < 2) ! 675: continue; ! 676: /* Its stuck */ ! 677: printf("Tty %x was stuck\n", tp); ! 678: nch = getc(&tp->t_outq); ! 679: outb(TXRX((int)tp->t_addr), nch); ! 680: } ! 681: ! 682: splx(s); ! 683: timeout(comtimer, 0, comtimer_interval*hz); ! 684: } ! 685: ! 686: /* ! 687: * Set receive modem state from modem status register. ! 688: */ ! 689: fix_modem_state(unit, modem_stat) ! 690: int unit, modem_stat; ! 691: { ! 692: int stat = 0; ! 693: ! 694: if (modem_stat & iCTS) ! 695: stat |= TM_CTS; /* clear to send */ ! 696: if (modem_stat & iDSR) ! 697: stat |= TM_DSR; /* data set ready */ ! 698: if (modem_stat & iRI) ! 699: stat |= TM_RNG; /* ring indicator */ ! 700: if (modem_stat & iRLSD) ! 701: stat |= TM_CAR; /* carrier? */ ! 702: ! 703: commodem[unit] = (commodem[unit] & ~(TM_CTS|TM_DSR|TM_RNG|TM_CAR)) ! 704: | stat; ! 705: } ! 706: ! 707: /* ! 708: * Modem change (input signals) ! 709: */ ! 710: commodem_intr( ! 711: int unit, ! 712: int stat) ! 713: { ! 714: int changed; ! 715: ! 716: changed = commodem[unit]; ! 717: fix_modem_state(unit, stat); ! 718: stat = commodem[unit]; ! 719: ! 720: /* Assumption: if the other party can handle ! 721: modem signals then it should handle all ! 722: the necessary ones. Else fix the cable. */ ! 723: ! 724: changed ^= stat; /* what changed ? */ ! 725: ! 726: if (changed & TM_CTS) ! 727: tty_cts( &com_tty[unit], stat & TM_CTS ); ! 728: ! 729: #if 0 ! 730: if (changed & TM_CAR) ! 731: ttymodem( &com_tty[unit], stat & TM_CAR ); ! 732: #endif ! 733: ! 734: } ! 735: ! 736: /* ! 737: * Set/get modem bits ! 738: */ ! 739: commctl( ! 740: register struct tty *tp, ! 741: int bits, ! 742: int how) ! 743: { ! 744: spl_t s; ! 745: int unit; ! 746: vm_offset_t dev_addr; ! 747: register int b; ! 748: ! 749: unit = minor(tp->t_dev); ! 750: ! 751: if (bits == TM_HUP) { /* close line (internal) */ ! 752: bits = TM_DTR | TM_RTS; ! 753: how = DMBIC; ! 754: } ! 755: ! 756: if (how == DMGET) return commodem[unit]; ! 757: ! 758: dev_addr = cominfo[unit]->address; ! 759: ! 760: s = spltty(); ! 761: ! 762: switch (how) { ! 763: case DMSET: ! 764: b = bits; break; ! 765: case DMBIS: ! 766: b = commodem[unit] | bits; break; ! 767: case DMBIC: ! 768: b = commodem[unit] & ~bits; break; ! 769: } ! 770: commodem[unit] = b; ! 771: ! 772: if (bits & TM_BRK) { ! 773: if (b & TM_BRK) { ! 774: outb(LINE_CTL(dev_addr), inb(LINE_CTL(dev_addr)) | iSETBREAK); ! 775: } else { ! 776: outb(LINE_CTL(dev_addr), inb(LINE_CTL(dev_addr)) & ~iSETBREAK); ! 777: } ! 778: } ! 779: ! 780: #if 0 ! 781: /* do I need to do something on this ? */ ! 782: if (bits & TM_LE) { /* line enable */ ! 783: } ! 784: #endif ! 785: #if 0 ! 786: /* Unsupported */ ! 787: if (bits & TM_ST) { /* secondary transmit */ ! 788: } ! 789: if (bits & TM_SR) { /* secondary receive */ ! 790: } ! 791: #endif ! 792: if (bits & (TM_DTR|TM_RTS)) { /* data terminal ready, request to send */ ! 793: how = iOUT2; ! 794: if (b & TM_DTR) how |= iDTR; ! 795: if (b & TM_RTS) how |= iRTS; ! 796: outb(MODEM_CTL(dev_addr), how); ! 797: } ! 798: ! 799: splx(s); ! 800: ! 801: /* the rest are inputs */ ! 802: return commodem[unit]; ! 803: } ! 804: ! 805: comstop(tp, flags) ! 806: register struct tty *tp; ! 807: int flags; ! 808: { ! 809: if ((tp->t_state & TS_BUSY) && (tp->t_state & TS_TTSTOP) == 0) ! 810: tp->t_state |= TS_FLUSH; ! 811: } ! 812: ! 813: /* ! 814: * ! 815: * Code to be called from debugger. ! 816: * ! 817: */ ! 818: void compr_addr(addr) ! 819: { ! 820: /* The two line_stat prints may show different values, since ! 821: * touching some of the registers constitutes changing them. ! 822: */ ! 823: printf("LINE_STAT(%x) %x\n", ! 824: LINE_STAT(addr), inb(LINE_STAT(addr))); ! 825: ! 826: printf("TXRX(%x) %x, INTR_ENAB(%x) %x, INTR_ID(%x) %x, LINE_CTL(%x) %x,\n\ ! 827: MODEM_CTL(%x) %x, LINE_STAT(%x) %x, MODEM_STAT(%x) %x\n", ! 828: TXRX(addr), inb(TXRX(addr)), ! 829: INTR_ENAB(addr), inb(INTR_ENAB(addr)), ! 830: INTR_ID(addr), inb(INTR_ID(addr)), ! 831: LINE_CTL(addr), inb(LINE_CTL(addr)), ! 832: MODEM_CTL(addr), inb(MODEM_CTL(addr)), ! 833: LINE_STAT(addr), inb(LINE_STAT(addr)), ! 834: MODEM_STAT(addr),inb(MODEM_STAT(addr))); ! 835: } ! 836: ! 837: int compr(unit) ! 838: { ! 839: compr_addr(cominfo[unit]->address); ! 840: return(0); ! 841: } ! 842: ! 843: int ! 844: comgetc(int unit) ! 845: { ! 846: u_short addr = (u_short)(cominfo[unit]->address); ! 847: spl_t s = spltty(); ! 848: int c; ! 849: ! 850: while((inb(LINE_STAT(addr)) & iDR) == 0) ; ! 851: ! 852: c = inb(TXRX(addr)); ! 853: splx(s); ! 854: return c; ! 855: } ! 856: ! 857: #if RCLINE >= 0 ! 858: /* ! 859: * Routines for the console ! 860: */ ! 861: int ! 862: comcnputc(dev_t dev, int c) ! 863: { ! 864: u_short addr = (u_short)(cominfo[minor(dev)]->address); ! 865: ! 866: /* Wait for transmitter to empty */ ! 867: while((inb(LINE_STAT(addr)) & iTHRE) == 0) ! 868: continue; ! 869: ! 870: /* send the char */ ! 871: if (c == '\n') ! 872: comcnputc(dev, '\r'); ! 873: outb(addr, c); ! 874: } ! 875: ! 876: int ! 877: comcngetc(dev_t dev, int wait) ! 878: { ! 879: u_short addr = (u_short)(cominfo[minor(dev)]->address); ! 880: int c; ! 881: ! 882: while((inb(LINE_STAT(addr)) & iDR) == 0) ! 883: if (! wait) ! 884: return 0; ! 885: ! 886: c = inb(TXRX(addr)); ! 887: return c & 0x7f; ! 888: } ! 889: #endif /* RCLINE */ ! 890: ! 891: #endif /* NCOM */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.