Annotation of 43BSDTahoe/sys/vaxuba/dmx.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1982, 1986 Regents of the University of California.
                      3:  * All rights reserved.  The Berkeley software License Agreement
                      4:  * specifies the terms and conditions for redistribution.
                      5:  *
                      6:  *     %W% (Berkeley) %G%
                      7:  */
                      8: 
                      9: /*
                     10:  * Common code for DMF32 and DMZ32 drivers
                     11:  */
                     12: #include "dmf.h"
                     13: #include "dmz.h"
                     14: #if NDMF + NDMZ > 0
                     15: 
                     16: #include "../machine/pte.h"
                     17: 
                     18: #include "bk.h"
                     19: #include "uba.h"
                     20: #include "param.h"
                     21: #include "conf.h"
                     22: #include "dir.h"
                     23: #include "user.h"
                     24: #include "proc.h"
                     25: #include "ioctl.h"
                     26: #include "tty.h"
                     27: #include "map.h"
                     28: #include "buf.h"
                     29: #include "vm.h"
                     30: #include "bkmac.h"
                     31: #include "clist.h"
                     32: #include "file.h"
                     33: #include "uio.h"
                     34: #include "kernel.h"
                     35: #include "syslog.h"
                     36: 
                     37: #include "dmx.h"
                     38: #include "ubareg.h"
                     39: #include "ubavar.h"
                     40: #include "dmxreg.h"
                     41: #include "dmreg.h"
                     42: 
                     43: #ifndef        PORTSELECTOR
                     44: #define        ISPEED  B9600
                     45: #define        IFLAGS  (EVENP|ODDP|ECHO)
                     46: #else
                     47: #define        ISPEED  B4800
                     48: #define        IFLAGS  (EVENP|ODDP)
                     49: #endif
                     50: 
                     51: #ifndef DMX_TIMEOUT
                     52: #define DMX_TIMEOUT    10
                     53: #endif
                     54: int    dmx_timeout = DMX_TIMEOUT;              /* silo timeout, in ms */
                     55: int    dmx_mindma = 4;                 /* don't dma below this point */
                     56: 
                     57: char   dmx_speeds[] =
                     58:        { 0, 0, 1, 2, 3, 4, 0, 5, 6, 7, 010, 012, 014, 016, 017, 0 };
                     59: 
                     60: /*
                     61:  * The clist space is mapped by the drivers onto each UNIBUS.
                     62:  * The UBACVT macro converts a clist space address for unibus uban
                     63:  * into an I/O space address for the DMA routine.
                     64:  */
                     65: int    cbase[NUBA];                    /* base address in unibus map */
                     66: #define        UBACVT(x, uban)         (cbase[uban] + ((x)-(char *)cfree))
                     67: 
                     68: int    ttrstrt();
                     69: 
                     70: /*
                     71:  * DMF/DMZ open common code
                     72:  */
                     73: dmxopen(tp, sc)
                     74:        register struct tty *tp;
                     75:        register struct dmx_softc *sc;
                     76: {
                     77:        int s, unit;
                     78: 
                     79:        s = spltty();
                     80:        if ((sc->dmx_flags & DMX_ACTIVE) == 0) {
                     81:                sc->dmx_octet->csr |= DMF_IE;
                     82:                sc->dmx_flags |= DMX_ACTIVE;
                     83:                sc->dmx_octet->rsp = dmx_timeout;
                     84:        }
                     85:        splx(s);
                     86:        if (tp->t_state & TS_XCLUDE && u.u_uid != 0)
                     87:                return (EBUSY);
                     88:        /*
                     89:         * If this is first open, initialize tty state to default.
                     90:         */
                     91:        if ((tp->t_state&TS_ISOPEN) == 0) {
                     92:                ttychars(tp);
                     93: #ifndef PORTSELECTOR
                     94:                if (tp->t_ispeed == 0) {
                     95: #else
                     96:                        tp->t_state |= TS_HUPCLS;
                     97: #endif PORTSELECTOR
                     98:                        tp->t_ispeed = ISPEED;
                     99:                        tp->t_ospeed = ISPEED;
                    100:                        tp->t_flags = IFLAGS;
                    101: #ifndef PORTSELECTOR
                    102:                }
                    103: #endif PORTSELECTOR
                    104:        }
                    105:        dmxparam(tp);
                    106: 
                    107:        unit = minor(tp->t_dev) & 07;
                    108:        /*
                    109:         * Wait for carrier, then process line discipline specific open.
                    110:         */
                    111:        s = spltty();
                    112:        for (;;) {
                    113:                if ((dmxmctl(tp, DMF_ON, DMSET) & DMF_CAR) ||
                    114:                    (sc->dmx_softCAR & (1 << unit)))
                    115:                        tp->t_state |= TS_CARR_ON;
                    116:                if (tp->t_state & TS_CARR_ON)
                    117:                        break;
                    118:                tp->t_state |= TS_WOPEN;
                    119:                sleep((caddr_t)&tp->t_rawq, TTIPRI);
                    120:        }
                    121:        splx(s);
                    122:        return ((*linesw[tp->t_line].l_open)(tp->t_dev, tp));
                    123: }
                    124: 
                    125: dmxclose(tp)
                    126:        register struct tty *tp;
                    127: {
                    128: 
                    129:        (*linesw[tp->t_line].l_close)(tp);
                    130:        (void) dmxmctl(tp, DMF_BRK, DMBIC);
                    131:        if (tp->t_state & TS_HUPCLS || (tp->t_state & TS_ISOPEN) == 0)
                    132:                (void) dmxmctl(tp, DMF_OFF, DMSET);
                    133:        ttyclose(tp);
                    134: }
                    135: 
                    136: dmxrint(sc)
                    137:        register struct dmx_softc *sc;
                    138: {
                    139:        register c;
                    140:        register struct tty *tp;
                    141:        register struct dmx_octet *addr;
                    142:        int unit;
                    143:        int overrun = 0;
                    144: 
                    145:        addr = (struct dmx_octet *)sc->dmx_octet;
                    146:        /*
                    147:         * Loop fetching characters from the silo for this
                    148:         * octet until there are no more in the silo.
                    149:         */
                    150:        while ((c = addr->rbuf) < 0) {
                    151: 
                    152:                unit = (c >> 8) & 07;
                    153:                tp = sc->dmx_tty + unit;
                    154:                if (c & DMF_DSC) {
                    155:                        addr->csr = DMF_IE | DMFIR_RMSTSC | unit;
                    156:                        if (addr->rmstsc & DMF_CAR)
                    157:                                (void)(*linesw[tp->t_line].l_modem)(tp, 1);
                    158:                        else if ((sc->dmx_softCAR & (1 << unit)) == 0 &&
                    159:                            (*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
                    160:                                addr->csr = DMF_IE | DMFIR_LCR | unit;
                    161:                                addr->lctms = DMF_ENA;
                    162:                        }
                    163:                        continue;
                    164:                }
                    165:                if ((tp->t_state&TS_ISOPEN) == 0) {
                    166:                        wakeup((caddr_t)&tp->t_rawq);
                    167: #ifdef PORTSELECTOR
                    168:                        if ((tp->t_state & TS_WOPEN) == 0)
                    169: #endif
                    170:                                continue;
                    171:                }
                    172:                if (c & (DMF_PE|DMF_DO|DMF_FE)) {
                    173:                        if (c & DMF_PE)
                    174:                                if ((tp->t_flags & (EVENP|ODDP)) == EVENP
                    175:                                || (tp->t_flags & (EVENP|ODDP)) == ODDP)
                    176:                                        continue;
                    177:                        if ((c & DMF_DO) && overrun == 0) {
                    178:                                log(LOG_WARNING,
                    179:                                    "dm%c%d: silo overflow, line %d\n",
                    180:                                    sc->dmx_type, sc->dmx_unit,
                    181:                                    sc->dmx_unit0 + unit);
                    182:                                overrun = 1;
                    183:                        }
                    184:                        if (c & DMF_FE)
                    185:                                /*
                    186:                                 * At framing error (break) generate
                    187:                                 * a null (in raw mode, for getty), or an
                    188:                                 * interrupt (in cooked/cbreak mode).
                    189:                                 */
                    190:                                if (tp->t_flags & RAW)
                    191:                                        c = 0;
                    192:                                else
                    193:                                        c = tp->t_intrc;
                    194:                }
                    195:                (*linesw[tp->t_line].l_rint)(c, tp);
                    196:        }
                    197: }
                    198: 
                    199: dmxioctl(tp, cmd, data, flag)
                    200:        register struct tty *tp;
                    201:        caddr_t data;
                    202: {
                    203:        int error;
                    204: 
                    205:        error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
                    206:        if (error >= 0)
                    207:                return (error);
                    208:        error = ttioctl(tp, cmd, data, flag);
                    209:        if (error >= 0) {
                    210:                if (cmd == TIOCSETP || cmd == TIOCSETN || cmd == TIOCLBIS ||
                    211:                    cmd == TIOCLBIC || cmd == TIOCLSET)
                    212:                        dmxparam(tp);
                    213:                return (error);
                    214:        }
                    215:        switch (cmd) {
                    216: 
                    217:        case TIOCSBRK:
                    218:                (void) dmxmctl(tp, DMF_BRK, DMBIS);
                    219:                break;
                    220: 
                    221:        case TIOCCBRK:
                    222:                (void) dmxmctl(tp, DMF_BRK, DMBIC);
                    223:                break;
                    224: 
                    225:        case TIOCSDTR:
                    226:                (void) dmxmctl(tp, DMF_DTR|DMF_RTS, DMBIS);
                    227:                break;
                    228: 
                    229:        case TIOCCDTR:
                    230:                (void) dmxmctl(tp, DMF_DTR|DMF_RTS, DMBIC);
                    231:                break;
                    232: 
                    233:        case TIOCMSET:
                    234:                (void) dmxmctl(tp, dmtodmx(*(int *)data), DMSET);
                    235:                break;
                    236: 
                    237:        case TIOCMBIS:
                    238:                (void) dmxmctl(tp, dmtodmx(*(int *)data), DMBIS);
                    239:                break;
                    240: 
                    241:        case TIOCMBIC:
                    242:                (void) dmxmctl(tp, dmtodmx(*(int *)data), DMBIC);
                    243:                break;
                    244: 
                    245:        case TIOCMGET:
                    246:                *(int *)data = dmxmctl(tp, 0, DMGET);
                    247:                break;
                    248: 
                    249:        default:
                    250:                return (ENOTTY);
                    251:        }
                    252:        return (0);
                    253: }
                    254: 
                    255: /*
                    256:  * modem control
                    257:  * "bits" are dmf/dmz lcr format;
                    258:  * return of DMGET is DM11 format.
                    259:  */
                    260: dmxmctl(tp, bits, how)
                    261:        struct tty *tp;
                    262:        int bits, how;
                    263: {
                    264:        register struct dmx_octet *addr;
                    265:        register int unit, mbits, lcr;
                    266:        int s;
                    267: 
                    268:        unit = minor(tp->t_dev) & 07;
                    269:        addr = (struct dmx_octet *)(tp->t_addr);
                    270: 
                    271:        s = spltty();
                    272:        addr->csr = DMF_IE | DMFIR_RMSTSC | unit;
                    273:        mbits = addr->rmstsc & 0xff00;
                    274:        addr->csr = DMF_IE | DMFIR_LCR | unit;
                    275:        lcr = addr->lctms;
                    276: 
                    277:        switch (how) {
                    278:        case DMSET:
                    279:                lcr = bits;
                    280:                break;
                    281: 
                    282:        case DMBIS:
                    283:                lcr |= bits;
                    284:                break;
                    285: 
                    286:        case DMBIC:
                    287:                lcr &= ~bits;
                    288:                break;
                    289: 
                    290:        case DMGET:
                    291:                splx(s);
                    292:                return (dmxtodm(mbits, lcr));
                    293:        }
                    294:        addr->lctms = lcr;
                    295:        (void) splx(s);
                    296:        return (mbits);
                    297: }
                    298: 
                    299: /*
                    300:  * Routine to convert modem status from dm to dmf/dmz lctmr format.
                    301:  */
                    302: dmtodmx(bits)
                    303:        register int bits;
                    304: {
                    305:        register int lcr = DMF_ENA;
                    306: 
                    307:        if (bits & DML_DTR)
                    308:                lcr |= DMF_DTR;
                    309:        if (bits & DML_RTS)
                    310:                lcr |= DMF_RTS;
                    311:        if (bits & DML_ST)
                    312:                lcr |= DMF_SRTS;
                    313:        if (bits & DML_USR)
                    314:                lcr |= DMF_USRW;
                    315:        return (lcr);
                    316: }
                    317: 
                    318: /*
                    319:  * Routine to convert modem status from dmf/dmz receive modem status
                    320:  * and line control register to dm format.
                    321:  * If dmf/dmz user modem read bit set, set DML_USR.
                    322:  */
                    323: dmxtodm(mstat, lcr)
                    324:        register int mstat, lcr;
                    325: {
                    326: 
                    327:        mstat = ((mstat & (DMF_DSR|DMF_RNG|DMF_CAR|DMF_CTS|DMF_SR)) >> 7) | 
                    328:                ((mstat & DMF_USRR) >> 1) | DML_LE;
                    329:        if (lcr & DMF_DTR)
                    330:                mstat |= DML_DTR;
                    331:        if (lcr & DMF_SRTS)
                    332:                mstat |= DML_ST;
                    333:        if (lcr & DMF_RTS)
                    334:                mstat |= DML_RTS;
                    335:        return (mstat);
                    336: }
                    337:  
                    338: 
                    339: /*
                    340:  * Set parameters from open or ioctl into the hardware registers.
                    341:  */
                    342: dmxparam(tp)
                    343:        register struct tty *tp;
                    344: {
                    345:        register struct dmx_octet *addr;
                    346:        register int lpar, lcr;
                    347:        int s, unit;
                    348: 
                    349:        addr = (struct dmx_octet *)tp->t_addr;
                    350:        unit = minor(tp->t_dev) & 07;
                    351:        /*
                    352:         * Block interrupts so parameters will be set
                    353:         * before the line interrupts.
                    354:         */
                    355:        s = spltty();
                    356:        addr->csr = unit | DMFIR_LCR | DMF_IE;
                    357:        if (tp->t_ispeed == 0) {
                    358:                tp->t_state |= TS_HUPCLS;
                    359:                (void) dmxmctl(tp, DMF_OFF, DMSET);
                    360:                splx(s);
                    361:                return;
                    362:        }
                    363:        lpar = (dmx_speeds[tp->t_ospeed]<<12) | (dmx_speeds[tp->t_ispeed]<<8);
                    364:        lcr = DMF_ENA;
                    365:        if ((tp->t_ispeed) == B134)
                    366:                lpar |= BITS6|PENABLE;
                    367:        else if (tp->t_flags & (RAW|LITOUT|PASS8))
                    368:                lpar |= BITS8;
                    369:        else {
                    370:                lpar |= BITS7|PENABLE;
                    371:                /* CHECK FOR XON/XOFF AND SET lcr |= DMF_AUTOX; */
                    372:        }
                    373:        if (tp->t_flags&EVENP)
                    374:                lpar |= EPAR;
                    375:        if ((tp->t_ospeed) == B110)
                    376:                lpar |= TWOSB;
                    377:        lpar |= (unit&07);
                    378:        addr->lpr = lpar;
                    379:        addr->lctms = (addr->lctms &~ 0xff) | lcr;
                    380:        splx(s);
                    381: }
                    382: 
                    383: /*
                    384:  * Process a transmit interrupt on an octet.
                    385:  */
                    386: dmxxint(sc)
                    387:        register struct dmx_softc *sc;
                    388: {
                    389:        register struct tty *tp;
                    390:        register struct dmx_octet *addr;
                    391:        register int t;
                    392: 
                    393:        addr = (struct dmx_octet *)sc->dmx_octet;
                    394:        while ((t = addr->csr) & DMF_TI) {
                    395:                if (t & DMF_NXM)
                    396:                        /* SHOULD RESTART OR SOMETHING... */
                    397:                        printf("dm%c%d: NXM line %d\n", sc->dmx_type,
                    398:                            sc->dmx_unit, sc->dmx_unit0 + (t >> 8 & 7));
                    399:                t = t >> 8 & 7;
                    400:                tp = sc->dmx_tty + t;
                    401:                tp->t_state &= ~TS_BUSY;
                    402:                if (tp->t_state & TS_FLUSH)
                    403:                        tp->t_state &= ~TS_FLUSH;
                    404: #define new
                    405: #ifndef new
                    406:                else if (sc->dmx_dmacount[t]) {
                    407:                        short cntr;
                    408: 
                    409:                        /*
                    410:                         * Do arithmetic in a short to make up
                    411:                         * for lost 16&17 bits.
                    412:                         */
                    413:                        addr->csr = DMFIR_TBA | DMF_IE | t;
                    414:                        cntr = addr->tba -
                    415:                            UBACVT(tp->t_outq.c_cf, sc->dmx_ubanum);
                    416:                        ndflush(&tp->t_outq, (int)cntr);
                    417:                }
                    418: #else
                    419:                else if (sc->dmx_dmacount[t])
                    420:                        ndflush(&tp->t_outq, sc->dmx_dmacount[t]);
                    421:                sc->dmx_dmacount[t] = 0;
                    422: #endif
                    423:                (*linesw[tp->t_line].l_start)(tp);
                    424:        }
                    425: }
                    426: 
                    427: dmxstart(tp, sc)
                    428:        register struct tty *tp;
                    429:        struct dmx_softc *sc;
                    430: {
                    431:        register struct dmx_octet *addr;
                    432:        register int unit, nch;
                    433:        int s;
                    434: 
                    435:        unit = minor(tp->t_dev) & 07;
                    436:        addr = (struct dmx_octet *)tp->t_addr;
                    437: 
                    438:        /*
                    439:         * Must hold interrupts in following code to prevent
                    440:         * state of the tp from changing.
                    441:         */
                    442:        s = spltty();
                    443:        /*
                    444:         * If it's currently active, or delaying, no need to do anything.
                    445:         */
                    446:        if (tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
                    447:                goto out;
                    448:        /*
                    449:         * If there are still characters to dma or in the silo,
                    450:         * just reenable the transmitter.
                    451:         */
                    452:        addr->csr = DMF_IE | DMFIR_TBUF | unit;
                    453: #ifdef new
                    454:        if (addr->tsc || sc->dmx_dmacount[unit]) {
                    455: #else
                    456:        if (addr->tsc) {
                    457: #endif
                    458:                addr->csr = DMF_IE | DMFIR_LCR | unit;
                    459:                addr->lctms = addr->lctms | DMF_TE;
                    460:                tp->t_state |= TS_BUSY;
                    461:                goto out;
                    462:        }
                    463:        /*
                    464:         * If there are sleepers, and output has drained below low
                    465:         * water mark, wake up the sleepers.
                    466:         */
                    467:        if (tp->t_outq.c_cc <= TTLOWAT(tp)) {
                    468:                if (tp->t_state & TS_ASLEEP) {
                    469:                        tp->t_state &= ~TS_ASLEEP;
                    470:                        wakeup((caddr_t)&tp->t_outq);
                    471:                }
                    472:                if (tp->t_wsel) {
                    473:                        selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
                    474:                        tp->t_wsel = 0;
                    475:                        tp->t_state &= ~TS_WCOLL;
                    476:                }
                    477:        }
                    478:        /*
                    479:         * Now restart transmission unless the output queue is
                    480:         * empty.
                    481:         */
                    482:        if (tp->t_outq.c_cc == 0)
                    483:                goto out;
                    484:        if (tp->t_flags & (RAW|LITOUT))
                    485:                nch = ndqb(&tp->t_outq, 0);
                    486:        else {
                    487:                if ((nch = ndqb(&tp->t_outq, 0200)) == 0) {
                    488:                        /*
                    489:                        * If first thing on queue is a delay process it.
                    490:                        */
                    491:                        nch = getc(&tp->t_outq);
                    492:                        timeout(ttrstrt, (caddr_t)tp, (nch&0x7f)+6);
                    493:                        tp->t_state |= TS_TIMEOUT;
                    494:                        goto out;
                    495:                }
                    496:        }
                    497:        /*
                    498:         * If characters to transmit, restart transmission.
                    499:         */
                    500:        if (nch >= dmx_mindma) {
                    501:                register car;
                    502: 
                    503:                sc->dmx_dmacount[unit] = nch;
                    504:                addr->csr = DMF_IE | DMFIR_LCR | unit;
                    505:                addr->lctms = addr->lctms | DMF_TE;
                    506:                car = UBACVT(tp->t_outq.c_cf, sc->dmx_ubanum);
                    507:                addr->csr = DMF_IE | DMFIR_TBA | unit;
                    508:                addr->tba = car;
                    509:                addr->tcc = ((car >> 2) & 0xc000) | nch;
                    510:                tp->t_state |= TS_BUSY;
                    511:        } else if (nch) {
                    512:                register char *cp = tp->t_outq.c_cf;
                    513:                register int i;
                    514: 
                    515: #ifndef new
                    516:                sc->dmx_dmacount[unit] = 0;
                    517: #endif
                    518:                nch = MIN(nch, DMF_SILOCNT);
                    519:                addr->csr = DMF_IE | DMFIR_LCR | unit;
                    520:                addr->lctms = addr->lctms | DMF_TE;
                    521:                addr->csr = DMF_IE | DMFIR_TBUF | unit;
                    522:                for (i = 0; i < nch; i++)
                    523:                        addr->tbuf = *cp++;
                    524:                ndflush(&tp->t_outq, nch);
                    525:                tp->t_state |= TS_BUSY;
                    526:        }
                    527: out:
                    528:        splx(s);
                    529: }
                    530: 
                    531: dmxstop(tp, sc, flag)
                    532:        register struct tty *tp;
                    533:        struct dmx_softc *sc;
                    534: {
                    535:        register struct dmx_octet *addr;
                    536:        register unit = minor(tp->t_dev) & 7;
                    537:        int s;
                    538: 
                    539:        addr = (struct dmx_octet *)tp->t_addr;
                    540:        /*
                    541:         * Block input/output interrupts while messing with state.
                    542:         */
                    543:        s = spltty();
                    544:        if (flag) {
                    545:                addr->csr = DMF_IE | DMFIR_TBUF | unit;
                    546:                if (addr->tsc) {
                    547:                        /*
                    548:                         * Flush regardless of whether we're transmitting
                    549:                         * (TS_BUSY), if the silo contains untransmitted
                    550:                         * characters.
                    551:                         */
                    552:                        addr->csr = DMFIR_LCR | unit | DMF_IE;
                    553:                        addr->lctms = addr->lctms | DMF_TE | DMF_FLUSH;
                    554:                        /* this will interrupt so let dmxxint handle the rest */
                    555:                        tp->t_state |= TS_FLUSH|TS_BUSY;
                    556:                }
                    557: /*#ifdef new*/
                    558:                sc->dmx_dmacount[unit] = 0;
                    559: /*#endif*/
                    560:        } else {
                    561:                /*
                    562:                 * Stop transmission by disabling
                    563:                 * the transmitter.  We'll pick up where we
                    564:                 * left off by reenabling in dmxstart.
                    565:                 */
                    566:                addr->csr = DMFIR_LCR | unit | DMF_IE;
                    567:                addr->lctms = addr->lctms &~ DMF_TE;
                    568:                /* no interrupt here */
                    569:                tp->t_state &= ~TS_BUSY;
                    570:        }
                    571:        splx(s);
                    572: }
                    573: #endif NDMF + NDMZ

unix.superglobalmegacorp.com

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