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