Annotation of Net2/arch/amiga/dev/ser.c, revision 1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.