|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1982, 1986, 1990 The Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution and use in source and binary forms, with or without ! 6: * modification, are permitted provided that the following conditions ! 7: * are met: ! 8: * 1. Redistributions of source code must retain the above copyright ! 9: * notice, this list of conditions and the following disclaimer. ! 10: * 2. Redistributions in binary form must reproduce the above copyright ! 11: * notice, this list of conditions and the following disclaimer in the ! 12: * documentation and/or other materials provided with the distribution. ! 13: * 3. All advertising materials mentioning features or use of this software ! 14: * must display the following acknowledgement: ! 15: * This product includes software developed by the University of ! 16: * California, Berkeley and its contributors. ! 17: * 4. Neither the name of the University nor the names of its contributors ! 18: * may be used to endorse or promote products derived from this software ! 19: * without specific prior written permission. ! 20: * ! 21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 31: * SUCH DAMAGE. ! 32: * ! 33: * @(#)ser.c 7.12 (Berkeley) 6/27/91 ! 34: */ ! 35: ! 36: #include "ser.h" ! 37: ! 38: #if NSER > 0 ! 39: #include "sys/param.h" ! 40: #include "sys/systm.h" ! 41: #include "sys/ioctl.h" ! 42: #include "sys/tty.h" ! 43: #include "sys/proc.h" ! 44: #include "sys/conf.h" ! 45: #include "sys/file.h" ! 46: #include "sys/malloc.h" ! 47: #include "sys/uio.h" ! 48: #include "sys/kernel.h" ! 49: #include "sys/syslog.h" ! 50: ! 51: #include "device.h" ! 52: #include "serreg.h" ! 53: #include "machine/cpu.h" ! 54: ! 55: #include "../amiga/custom.h" ! 56: #include "../amiga/cia.h" ! 57: ! 58: int serprobe(); ! 59: struct driver serdriver = { ! 60: serprobe, "ser", ! 61: }; ! 62: ! 63: int serstart(), serparam(), serintr(); ! 64: int sersoftCAR; ! 65: int ser_active; ! 66: int ser_hasfifo; ! 67: int nser = NSER; ! 68: #ifdef SERCONSOLE ! 69: int serconsole = SERCONSOLE; ! 70: #else ! 71: int serconsole = -1; ! 72: #endif ! 73: int serconsinit; ! 74: int serdefaultrate = TTYDEF_SPEED; ! 75: int sermajor; ! 76: struct serdevice *ser_addr[NSER]; ! 77: struct tty ser_cons; ! 78: struct tty *ser_tty[NSER] = { &ser_cons }; ! 79: ! 80: struct speedtab serspeedtab[] = { ! 81: 0, 0, ! 82: 50, SERBRD(50), ! 83: 75, SERBRD(75), ! 84: 110, SERBRD(110), ! 85: 134, SERBRD(134), ! 86: 150, SERBRD(150), ! 87: 200, SERBRD(200), ! 88: 300, SERBRD(300), ! 89: 600, SERBRD(600), ! 90: 1200, SERBRD(1200), ! 91: 1800, SERBRD(1800), ! 92: 2400, SERBRD(2400), ! 93: 4800, SERBRD(4800), ! 94: 9600, SERBRD(9600), ! 95: 19200, SERBRD(19200), ! 96: 38400, SERBRD(38400), ! 97: -1, -1 ! 98: }; ! 99: ! 100: ! 101: /* since this UART is not particularly bright (nice put), we'll have to do ! 102: parity stuff on our own. this table contains the 8th bit in 7bit character ! 103: mode, for even parity. If you want odd parity, flip the bit. (for ! 104: generation of the table, see genpar.c) */ ! 105: ! 106: u_char even_parity[] = { ! 107: 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, ! 108: 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, ! 109: 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, ! 110: 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, ! 111: 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, ! 112: 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, ! 113: 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, ! 114: 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, ! 115: }; ! 116: ! 117: ! 118: /* since we don't get interrupts for changes on the modem control line, ! 119: well have to fake them by comparing current settings to the settings ! 120: we remembered on last invocation. */ ! 121: u_char last_ciab_pra; ! 122: ! 123: extern struct tty *constty; ! 124: #ifdef KGDB ! 125: #include "machine/remote-sl.h" ! 126: ! 127: extern dev_t kgdb_dev; ! 128: extern int kgdb_rate; ! 129: extern int kgdb_debug_init; ! 130: #endif ! 131: ! 132: #if 0 ! 133: #define UNIT(x) minor(x) ! 134: #else ! 135: /* just always force this to 0, so we can later interprete special ! 136: settings out of the unit number.. */ ! 137: #define UNIT(x) 0 ! 138: #endif ! 139: ! 140: #ifdef DEBUG ! 141: long fifoin[17]; ! 142: long fifoout[17]; ! 143: long serintrcount[16]; ! 144: long sermintcount[16]; ! 145: #endif ! 146: ! 147: serprobe(ad) ! 148: register struct amiga_device *ad; ! 149: { ! 150: register struct serdevice *ser; ! 151: register int unit; ! 152: ! 153: ser = (struct serdevice *) ad->amiga_addr; ! 154: unit = ad->amiga_unit; ! 155: if (unit == serconsole) ! 156: DELAY(100000); ! 157: ! 158: ad->amiga_ipl = 2; ! 159: ser_addr[unit] = ser; ! 160: ser_active |= 1 << unit; ! 161: sersoftCAR = ad->amiga_flags; ! 162: #ifdef KGDB ! 163: if (kgdb_dev == makedev(sermajor, unit)) { ! 164: if (serconsole == unit) ! 165: kgdb_dev = NODEV; /* can't debug over console port */ ! 166: else { ! 167: (void) serinit(unit, kgdb_rate); ! 168: serconsinit = 1; /* don't re-init in serputc */ ! 169: if (kgdb_debug_init) { ! 170: /* ! 171: * Print prefix of device name, ! 172: * let kgdb_connect print the rest. ! 173: */ ! 174: printf("ser%d: ", unit); ! 175: kgdb_connect(1); ! 176: } else ! 177: printf("ser%d: kgdb enabled\n", unit); ! 178: } ! 179: } ! 180: #endif ! 181: /* ! 182: * Need to reset baud rate, etc. of next print so reset serconsinit. ! 183: * Also make sure console is always "hardwired." ! 184: */ ! 185: if (unit == serconsole) { ! 186: serconsinit = 0; ! 187: sersoftCAR |= (1 << unit); ! 188: } ! 189: return (1); ! 190: } ! 191: ! 192: /* ARGSUSED */ ! 193: #ifdef __STDC__ ! 194: seropen(dev_t dev, int flag, int mode, struct proc *p) ! 195: #else ! 196: seropen(dev, flag, mode, p) ! 197: dev_t dev; ! 198: int flag, mode; ! 199: struct proc *p; ! 200: #endif ! 201: { ! 202: register struct tty *tp; ! 203: register int unit; ! 204: int error = 0; ! 205: ! 206: unit = minor (dev); ! 207: ! 208: if (unit == 1) ! 209: { ! 210: unit = 0; ! 211: sersoftCAR = 0; ! 212: } ! 213: else if (unit == 2) ! 214: { ! 215: unit = 0; ! 216: sersoftCAR = 0xff; ! 217: } ! 218: else ! 219: unit = 0; ! 220: ! 221: if (unit >= NSER || (ser_active & (1 << unit)) == 0) ! 222: return (ENXIO); ! 223: if(!ser_tty[unit]) { ! 224: MALLOC(tp, struct tty *, sizeof(struct tty), M_TTYS, M_WAITOK); ! 225: bzero(tp, sizeof(struct tty)); ! 226: ser_tty[unit] = tp; ! 227: } else ! 228: tp = ser_tty[unit]; ! 229: tp->t_oproc = serstart; ! 230: tp->t_param = serparam; ! 231: tp->t_dev = dev; ! 232: if ((tp->t_state & TS_ISOPEN) == 0) { ! 233: tp->t_state |= TS_WOPEN; ! 234: ttychars(tp); ! 235: if (tp->t_ispeed == 0) { ! 236: tp->t_iflag = TTYDEF_IFLAG | IXOFF; /* XXXXX */ ! 237: tp->t_oflag = TTYDEF_OFLAG; ! 238: #if 0 ! 239: tp->t_cflag = TTYDEF_CFLAG; ! 240: #else ! 241: tp->t_cflag = (CREAD | CS8 | CLOCAL); /* XXXXX */ ! 242: #endif ! 243: tp->t_lflag = TTYDEF_LFLAG; ! 244: tp->t_ispeed = tp->t_ospeed = serdefaultrate; ! 245: } ! 246: serparam(tp, &tp->t_termios); ! 247: ttsetwater(tp); ! 248: } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0) ! 249: return (EBUSY); ! 250: (void) sermctl (dev, TIOCM_DTR | TIOCM_RTS, DMSET); ! 251: if ((sersoftCAR & (1 << unit)) || (sermctl(dev, 0, DMGET) & TIOCM_CD)) ! 252: tp->t_state |= TS_CARR_ON; ! 253: (void) spltty(); ! 254: while ((flag&O_NONBLOCK) == 0 && (tp->t_cflag&CLOCAL) == 0 && ! 255: (tp->t_state & TS_CARR_ON) == 0) { ! 256: tp->t_state |= TS_WOPEN; ! 257: if (error = ttysleep(tp, (caddr_t)&tp->t_raw, TTIPRI | PCATCH, ! 258: ttopen, 0)) ! 259: break; ! 260: } ! 261: (void) spl0(); ! 262: if (error == 0) ! 263: error = (*linesw[tp->t_line].l_open)(dev, tp); ! 264: return (error); ! 265: } ! 266: ! 267: /*ARGSUSED*/ ! 268: serclose(dev, flag, mode, p) ! 269: dev_t dev; ! 270: int flag, mode; ! 271: struct proc *p; ! 272: { ! 273: register struct tty *tp; ! 274: register struct serdevice *ser; ! 275: register int unit; ! 276: ! 277: unit = UNIT(dev); ! 278: ! 279: ser = ser_addr[unit]; ! 280: tp = ser_tty[unit]; ! 281: (*linesw[tp->t_line].l_close)(tp, flag); ! 282: custom.adkcon = ADKCONF_UARTBRK; /* clear break */ ! 283: #ifdef KGDB ! 284: /* do not disable interrupts if debugging */ ! 285: if (dev != kgdb_dev) ! 286: #endif ! 287: custom.intena = INTF_RBF | INTF_VERTB; /* clear interrupt enable */ ! 288: custom.intreq = INTF_RBF | INTF_VERTB; /* and interrupt request */ ! 289: #if 0 ! 290: /* if the device is closed, it's close, no matter whether we deal with modem ! 291: control signals nor not. */ ! 292: if (tp->t_cflag&HUPCL || tp->t_state&TS_WOPEN || ! 293: (tp->t_state&TS_ISOPEN) == 0) ! 294: #endif ! 295: (void) sermctl(dev, 0, DMSET); ! 296: ttyclose(tp); ! 297: #if 0 ! 298: if (tp != &ser_cons) ! 299: { ! 300: FREE(tp, M_TTYS); ! 301: ser_tty[unit] = (struct tty *)NULL; ! 302: } ! 303: #endif ! 304: return (0); ! 305: } ! 306: ! 307: serread(dev, uio, flag) ! 308: dev_t dev; ! 309: struct uio *uio; ! 310: { ! 311: register struct tty *tp = ser_tty[UNIT(dev)]; ! 312: int error = (*linesw[tp->t_line].l_read)(tp, uio, flag); ! 313: ! 314: return error; ! 315: } ! 316: ! 317: serwrite(dev, uio, flag) ! 318: dev_t dev; ! 319: struct uio *uio; ! 320: { ! 321: int unit = UNIT(dev); ! 322: register struct tty *tp = ser_tty[unit]; ! 323: ! 324: /* ! 325: * (XXX) We disallow virtual consoles if the physical console is ! 326: * a serial port. This is in case there is a display attached that ! 327: * is not the console. In that situation we don't need/want the X ! 328: * server taking over the console. ! 329: */ ! 330: if (constty && unit == serconsole) ! 331: constty = NULL; ! 332: return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); ! 333: } ! 334: ! 335: serintr(unit) ! 336: register int unit; ! 337: { ! 338: register struct serdevice *ser; ! 339: register u_short code; ! 340: register u_char ch; ! 341: register u_short ints; ! 342: register struct tty *tp; ! 343: ! 344: ser = ser_addr[unit]; ! 345: ! 346: again: ! 347: ints = custom.intreqr & INTF_RBF; ! 348: if (! ints) ! 349: return 0; ! 350: ! 351: /* clear interrupt(s) */ ! 352: custom.intreq = ints; ! 353: ! 354: /* this register contains both data and status bits! */ ! 355: code = custom.serdatr; ! 356: ! 357: if (ints & INTF_RBF) ! 358: { ! 359: tp = ser_tty[unit]; ! 360: /* ! 361: * Process a received byte. Inline for speed... ! 362: */ ! 363: #ifdef KGDB ! 364: #define RCVBYTE() \ ! 365: ch = code & 0xff; \ ! 366: if ((tp->t_state & TS_ISOPEN) == 0) { \ ! 367: if (ch == FRAME_END && \ ! 368: kgdb_dev == makedev(sermajor, unit)) \ ! 369: kgdb_connect(0); /* trap into kgdb */ \ ! 370: } ! 371: #else ! 372: #define RCVBYTE() ! 373: #endif ! 374: RCVBYTE(); ! 375: /* sereint does the receive-processing */ ! 376: sereint (unit, code, ser); ! 377: } ! 378: ! 379: /* fake modem-control interrupt */ ! 380: sermint (unit, ser); ! 381: /* try to save interrupt load.. */ ! 382: goto again; ! 383: } ! 384: ! 385: sereint(unit, stat, ser) ! 386: register int unit, stat; ! 387: register struct serdevice *ser; ! 388: { ! 389: register struct tty *tp; ! 390: register int c; ! 391: register u_char ch; ! 392: ! 393: tp = ser_tty[unit]; ! 394: if ((tp->t_state & TS_ISOPEN) == 0) { ! 395: #ifdef KGDB ! 396: /* we don't care about parity errors */ ! 397: if (kgdb_dev == makedev(sermajor, unit) && c == FRAME_END) ! 398: kgdb_connect(0); /* trap into kgdb */ ! 399: #endif ! 400: return; ! 401: } ! 402: ch = stat & 0xff; ! 403: c = ch; ! 404: /* all databits 0 including stop indicate break condition */ ! 405: if (!(stat & 0x1ff)) ! 406: c |= TTY_FE; ! 407: ! 408: /* if parity checking enabled, check parity */ ! 409: else if ((tp->t_cflag & PARENB) && ! 410: (((ch >> 7) + even_parity[ch & 0x7f] + !!(tp->t_cflag & PARODD)) & 1)) ! 411: c |= TTY_PE; ! 412: ! 413: if (stat & SERDATRF_OVRUN) ! 414: log(LOG_WARNING, "ser%d: silo overflow\n", unit); ! 415: ! 416: (*linesw[tp->t_line].l_rint)(c, tp); ! 417: } ! 418: ! 419: sermint(unit) ! 420: register int unit; ! 421: { ! 422: register struct tty *tp; ! 423: register u_char stat, last, istat; ! 424: register struct serdevice *ser; ! 425: ! 426: tp = ser_tty[unit]; ! 427: stat = ciab.pra; ! 428: last = last_ciab_pra; ! 429: last_ciab_pra = stat; ! 430: ! 431: /* check whether any interesting signal changed state */ ! 432: istat = stat ^ last; ! 433: ! 434: if ((istat & CIAB_PRA_CD) && (sersoftCAR & (1 << unit)) == 0) ! 435: { ! 436: if (ISDCD (stat)) ! 437: (*linesw[tp->t_line].l_modem)(tp, 1); ! 438: else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0) ! 439: { ! 440: CLRDTR (stat); ! 441: CLRRTS (stat); ! 442: ciab.pra = stat; ! 443: last_ciab_pra = stat; ! 444: } ! 445: } ! 446: else if ((istat & CIAB_PRA_CTS) && (tp->t_state & TS_ISOPEN) && ! 447: (tp->t_flags & CRTSCTS)) ! 448: { ! 449: /* the line is up and we want to do rts/cts flow control */ ! 450: if (ISCTS (stat)) ! 451: { ! 452: tp->t_state &=~ TS_TTSTOP; ! 453: ttstart(tp); ! 454: } ! 455: else ! 456: tp->t_state |= TS_TTSTOP; ! 457: } ! 458: } ! 459: ! 460: serioctl(dev, cmd, data, flag) ! 461: dev_t dev; ! 462: caddr_t data; ! 463: { ! 464: register struct tty *tp; ! 465: register int unit = UNIT(dev); ! 466: register struct serdevice *ser; ! 467: register int error; ! 468: ! 469: tp = ser_tty[unit]; ! 470: error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); ! 471: if (error >= 0) ! 472: return (error); ! 473: error = ttioctl(tp, cmd, data, flag); ! 474: if (error >= 0) ! 475: return (error); ! 476: ! 477: ser = ser_addr[unit]; ! 478: switch (cmd) { ! 479: ! 480: case TIOCSBRK: ! 481: custom.adkcon = ADKCONF_SETCLR | ADKCONF_UARTBRK; ! 482: break; ! 483: ! 484: case TIOCCBRK: ! 485: custom.adkcon = ADKCONF_UARTBRK; ! 486: break; ! 487: ! 488: case TIOCSDTR: ! 489: (void) sermctl(dev, TIOCM_DTR | TIOCM_RTS, DMBIS); ! 490: break; ! 491: ! 492: case TIOCCDTR: ! 493: (void) sermctl(dev, TIOCM_DTR | TIOCM_RTS, DMBIC); ! 494: break; ! 495: ! 496: case TIOCMSET: ! 497: (void) sermctl(dev, *(int *)data, DMSET); ! 498: break; ! 499: ! 500: case TIOCMBIS: ! 501: (void) sermctl(dev, *(int *)data, DMBIS); ! 502: break; ! 503: ! 504: case TIOCMBIC: ! 505: (void) sermctl(dev, *(int *)data, DMBIC); ! 506: break; ! 507: ! 508: case TIOCMGET: ! 509: *(int *)data = sermctl(dev, 0, DMGET); ! 510: break; ! 511: ! 512: default: ! 513: return (ENOTTY); ! 514: } ! 515: return (0); ! 516: } ! 517: ! 518: serparam(tp, t) ! 519: register struct tty *tp; ! 520: register struct termios *t; ! 521: { ! 522: register struct serdevice *ser; ! 523: register int cfcr, cflag = t->c_cflag; ! 524: int unit = UNIT(tp->t_dev); ! 525: int ospeed = ttspeedtab(t->c_ospeed, serspeedtab); ! 526: ! 527: /* check requested parameters */ ! 528: if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed)) ! 529: return (EINVAL); ! 530: /* and copy to tty */ ! 531: tp->t_ispeed = t->c_ispeed; ! 532: tp->t_ospeed = t->c_ospeed; ! 533: tp->t_cflag = cflag; ! 534: ! 535: custom.intena = INTF_SETCLR | INTF_RBF; ! 536: custom.intreq = INTF_RBF; ! 537: last_ciab_pra = ciab.pra; ! 538: ! 539: if (ospeed == 0) { ! 540: (void) sermctl(unit, 0, DMSET); /* hang up line */ ! 541: return (0); ! 542: } ! 543: /* set the baud rate */ ! 544: custom.serper = (0<<15) | ospeed; /* select 8 bit mode (instead of 9 bit) */ ! 545: ! 546: return (0); ! 547: } ! 548: ! 549: serstart(tp) ! 550: register struct tty *tp; ! 551: { ! 552: register struct serdevice *ser; ! 553: int s, unit; ! 554: u_short c; ! 555: ! 556: unit = UNIT(tp->t_dev); ! 557: ser = ser_addr[unit]; ! 558: s = spltty(); ! 559: again: ! 560: if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP)) ! 561: goto out; ! 562: if (RB_LEN(&tp->t_out) <= tp->t_lowat) { ! 563: if (tp->t_state&TS_ASLEEP) { ! 564: tp->t_state &= ~TS_ASLEEP; ! 565: wakeup((caddr_t)&tp->t_out); ! 566: } ! 567: selwakeup (&tp->t_wsel); ! 568: } ! 569: if (RB_LEN(&tp->t_out) == 0) ! 570: goto out; ! 571: ! 572: while (! (custom.serdatr & SERDATRF_TBE)) ; ! 573: ! 574: c = rbgetc(&tp->t_out); ! 575: /* tp->t_state |= TS_BUSY; */ ! 576: ! 577: /* handle truncation of character if necessary */ ! 578: if ((tp->t_cflag & CSIZE) == CS7) ! 579: c &= 0x7f; ! 580: ! 581: /* handle parity if necessary (forces CS7) */ ! 582: if (tp->t_cflag & PARENB) ! 583: { ! 584: if (even_parity[c & 0x7f]) ! 585: c |= 0x80; ! 586: if (tp->t_cflag & PARODD) ! 587: c ^= 0x80; ! 588: } ! 589: ! 590: /* add stop bit(s) */ ! 591: if (tp->t_cflag & CSTOPB) ! 592: c |= 0x300; ! 593: else ! 594: c |= 0x100; ! 595: ! 596: custom.serdat = c; ! 597: ! 598: /* if there's input on the line, stop spitting out characters */ ! 599: if (! (custom.intreqr & INTF_RBF)) ! 600: goto again; ! 601: ! 602: out: ! 603: splx(s); ! 604: } ! 605: ! 606: /* ! 607: * Stop output on a line. ! 608: */ ! 609: /*ARGSUSED*/ ! 610: serstop(tp, flag) ! 611: register struct tty *tp; ! 612: { ! 613: register int s; ! 614: ! 615: s = spltty(); ! 616: if (tp->t_state & TS_BUSY) { ! 617: if ((tp->t_state&TS_TTSTOP)==0) ! 618: tp->t_state |= TS_FLUSH; ! 619: } ! 620: splx(s); ! 621: } ! 622: ! 623: sermctl(dev, bits, how) ! 624: dev_t dev; ! 625: int bits, how; ! 626: { ! 627: register struct serdevice *ser; ! 628: register int unit; ! 629: u_char ub; ! 630: int s; ! 631: ! 632: unit = UNIT(dev); ! 633: ser = ser_addr[unit]; ! 634: ! 635: /* convert TIOCM* mask into CIA mask (which is really low-active!!) */ ! 636: if (how != DMGET) ! 637: { ! 638: ub = 0; ! 639: if (bits & TIOCM_DTR) ub |= CIAB_PRA_DTR; ! 640: if (bits & TIOCM_RTS) ub |= CIAB_PRA_RTS; ! 641: if (bits & TIOCM_CTS) ub |= CIAB_PRA_CTS; ! 642: if (bits & TIOCM_CD) ub |= CIAB_PRA_CD; ! 643: if (bits & TIOCM_RI) ub |= CIAB_PRA_SEL; /* collision with /dev/par ! */ ! 644: if (bits & TIOCM_DSR) ub |= CIAB_PRA_DSR; ! 645: } ! 646: ! 647: ! 648: s = spltty(); ! 649: switch (how) { ! 650: ! 651: case DMSET: ! 652: /* invert and set */ ! 653: ciab.pra = ~ub; ! 654: break; ! 655: ! 656: case DMBIC: ! 657: ciab.pra |= ub; ! 658: ub = ~ciab.pra; ! 659: break; ! 660: ! 661: case DMBIS: ! 662: ciab.pra &= ~ub; ! 663: ub = ~ciab.pra; ! 664: break; ! 665: ! 666: case DMGET: ! 667: ub = ~ciab.pra; ! 668: break; ! 669: } ! 670: (void) splx(s); ! 671: ! 672: bits = 0; ! 673: if (ub & CIAB_PRA_DTR) bits |= TIOCM_DTR; ! 674: if (ub & CIAB_PRA_RTS) bits |= TIOCM_RTS; ! 675: if (ub & CIAB_PRA_CTS) bits |= TIOCM_CTS; ! 676: if (ub & CIAB_PRA_CD) bits |= TIOCM_CD; ! 677: if (ub & CIAB_PRA_SEL) bits |= TIOCM_RI; ! 678: if (ub & CIAB_PRA_DSR) bits |= TIOCM_DSR; ! 679: ! 680: return bits; ! 681: } ! 682: ! 683: /* ! 684: * Following are all routines needed for SER to act as console ! 685: */ ! 686: #include "../amiga/cons.h" ! 687: ! 688: sercnprobe(cp) ! 689: struct consdev *cp; ! 690: { ! 691: int unit = CONUNIT; ! 692: ! 693: /* locate the major number */ ! 694: for (sermajor = 0; sermajor < nchrdev; sermajor++) ! 695: if (cdevsw[sermajor].d_open == seropen) ! 696: break; ! 697: ! 698: /* XXX: ick */ ! 699: unit = CONUNIT; ! 700: ! 701: /* initialize required fields */ ! 702: cp->cn_dev = makedev(sermajor, unit); ! 703: cp->cn_tp = ser_tty[unit]; ! 704: cp->cn_pri = CN_NORMAL; ! 705: ! 706: /* ! 707: * If serconsole is initialized, raise our priority. ! 708: */ ! 709: if (serconsole == unit) ! 710: cp->cn_pri = CN_REMOTE; ! 711: #ifdef KGDB ! 712: if (major(kgdb_dev) == 1) /* XXX */ ! 713: kgdb_dev = makedev(sermajor, minor(kgdb_dev)); ! 714: #endif ! 715: } ! 716: ! 717: sercninit(cp) ! 718: struct consdev *cp; ! 719: { ! 720: int unit = UNIT(cp->cn_dev); ! 721: ! 722: serinit(unit, serdefaultrate); ! 723: serconsole = unit; ! 724: serconsinit = 1; ! 725: } ! 726: ! 727: serinit(unit, rate) ! 728: int unit, rate; ! 729: { ! 730: int s; ! 731: ! 732: #ifdef lint ! 733: stat = unit; if (stat) return; ! 734: #endif ! 735: s = splhigh(); ! 736: /* might want to fiddle with the CIA later ??? */ ! 737: custom.serper = ttspeedtab(rate, serspeedtab); ! 738: splx(s); ! 739: } ! 740: ! 741: sercngetc(dev) ! 742: { ! 743: u_short stat; ! 744: int c, s; ! 745: ! 746: #ifdef lint ! 747: stat = dev; if (stat) return (0); ! 748: #endif ! 749: s = splhigh(); ! 750: while (!((stat = custom.serdatr & 0xffff) & SERDATRF_RBF)) ! 751: ; ! 752: c = stat & 0xff; ! 753: /* clear interrupt */ ! 754: custom.intreq = INTF_RBF; ! 755: splx(s); ! 756: return (c); ! 757: } ! 758: ! 759: /* ! 760: * Console kernel output character routine. ! 761: */ ! 762: sercnputc(dev, c) ! 763: dev_t dev; ! 764: register int c; ! 765: { ! 766: register int timo; ! 767: short stat; ! 768: int s = splhigh(); ! 769: ! 770: #ifdef lint ! 771: stat = dev; if (stat) return; ! 772: #endif ! 773: if (serconsinit == 0) { ! 774: (void) serinit(UNIT(dev), serdefaultrate); ! 775: serconsinit = 1; ! 776: } ! 777: /* wait for any pending transmission to finish */ ! 778: timo = 50000; ! 779: while (! (custom.serdatr & SERDATRF_TBE) && --timo) ! 780: ; ! 781: custom.serdat = (c&0xff) | 0x100; ! 782: /* wait for this transmission to complete */ ! 783: timo = 1500000; ! 784: while (! (custom.serdatr & SERDATRF_TBE) && --timo) ! 785: ; ! 786: /* wait for the device (my vt100..) to process the data, since ! 787: we don't do flow-control with cnputc */ ! 788: for (timo = 0; timo < 30000; timo++) ; ! 789: ! 790: /* clear any interrupts generated by this transmission */ ! 791: custom.intreq = INTF_TBE; ! 792: splx(s); ! 793: } ! 794: ! 795: ! 796: serspit(c) ! 797: int c; ! 798: { ! 799: register struct Custom *cu asm("a2") = CUSTOMbase; ! 800: register int timo asm("d2"); ! 801: extern int cold; ! 802: int s; ! 803: ! 804: if (c == 10) ! 805: serspit (13); ! 806: ! 807: s = splhigh(); ! 808: ! 809: /* wait for any pending transmission to finish */ ! 810: timo = 500000; ! 811: while (! (cu->serdatr & (SERDATRF_TBE|SERDATRF_TSRE)) && --timo) ! 812: ; ! 813: cu->serdat = (c&0xff) | 0x100; ! 814: /* wait for this transmission to complete */ ! 815: timo = 15000000; ! 816: while (! (cu->serdatr & SERDATRF_TBE) && --timo) ! 817: ; ! 818: /* clear any interrupts generated by this transmission */ ! 819: cu->intreq = INTF_TBE; ! 820: ! 821: for (timo = 0; timo < 30000; timo++) ; ! 822: ! 823: splx (s); ! 824: } ! 825: ! 826: int ! 827: serselect(dev, rw, p) ! 828: dev_t dev; ! 829: int rw; ! 830: struct proc *p; ! 831: { ! 832: register struct tty *tp = ser_tty[UNIT(dev)]; ! 833: int nread; ! 834: int s = spltty(); ! 835: struct proc *selp; ! 836: ! 837: switch (rw) { ! 838: ! 839: case FREAD: ! 840: nread = ttnread(tp); ! 841: if (nread > 0 || ! 842: ((tp->t_cflag&CLOCAL) == 0 && (tp->t_state&TS_CARR_ON) == 0)) ! 843: goto win; ! 844: selrecord(p, &tp->t_rsel); ! 845: break; ! 846: ! 847: case FWRITE: ! 848: if (RB_LEN(&tp->t_out) <= tp->t_lowat) ! 849: goto win; ! 850: selrecord(p, &tp->t_wsel); ! 851: break; ! 852: } ! 853: splx(s); ! 854: return (0); ! 855: win: ! 856: splx(s); ! 857: return (1); ! 858: } ! 859: ! 860: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.