Annotation of 43BSD/sys/vaxuba/dhu.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1985, 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:  *     @(#)dhu.c       7.1 (Berkeley) 6/5/86
                      7:  */
                      8: 
                      9: /*
                     10:  * based on    dh.c 6.3        84/03/15
                     11:  * and on      dmf.c   6.2     84/02/16
                     12:  *
                     13:  * Dave Johnson, Brown University Computer Science
                     14:  *     ddj%brown@csnet-relay
                     15:  */
                     16: 
                     17: #include "dhu.h"
                     18: #if NDHU > 0
                     19: /*
                     20:  * DHU-11 driver
                     21:  */
                     22: #include "../machine/pte.h"
                     23: 
                     24: #include "bk.h"
                     25: #include "param.h"
                     26: #include "conf.h"
                     27: #include "dir.h"
                     28: #include "user.h"
                     29: #include "proc.h"
                     30: #include "ioctl.h"
                     31: #include "tty.h"
                     32: #include "map.h"
                     33: #include "buf.h"
                     34: #include "vm.h"
                     35: #include "kernel.h"
                     36: #include "syslog.h"
                     37: 
                     38: #include "uba.h"
                     39: #include "ubareg.h"
                     40: #include "ubavar.h"
                     41: #include "dhureg.h"
                     42: 
                     43: #include "bkmac.h"
                     44: #include "clist.h"
                     45: #include "file.h"
                     46: #include "uio.h"
                     47: 
                     48: /*
                     49:  * Definition of the driver for the auto-configuration program.
                     50:  */
                     51: int    dhuprobe(), dhuattach(), dhurint(), dhuxint();
                     52: struct uba_device *dhuinfo[NDHU];
                     53: u_short dhustd[] = { 160440, 160500, 0 };      /* some common addresses */
                     54: struct uba_driver dhudriver =
                     55:        { dhuprobe, 0, dhuattach, 0, dhustd, "dhu", dhuinfo };
                     56: 
                     57: #define        NDHULINE        (NDHU*16)
                     58: 
                     59: #define        UNIT(x) (minor(x))
                     60: 
                     61: #ifndef PORTSELECTOR
                     62: #define ISPEED B9600
                     63: #define IFLAGS (EVENP|ODDP|ECHO)
                     64: #else
                     65: #define ISPEED B4800
                     66: #define IFLAGS (EVENP|ODDP)
                     67: #endif
                     68: 
                     69: /*
                     70:  * default receive silo timeout value -- valid values are 2..255
                     71:  * number of ms. to delay between first char received and receive interrupt
                     72:  *
                     73:  * A value of 20 gives same response as ABLE dh/dm with silo alarm = 0
                     74:  */
                     75: #define        DHU_DEF_TIMO    20
                     76: 
                     77: /*
                     78:  * Other values for silo timeout register defined here but not used:
                     79:  * receive interrupt only on modem control or silo alarm (3/4 full)
                     80:  */
                     81: #define DHU_POLL_TIMO  0
                     82: /*
                     83:  * receive interrupt immediately on receive character
                     84:  */
                     85: #define DHU_NO_TIMO    1
                     86: 
                     87: /*
                     88:  * Local variables for the driver
                     89:  */
                     90: /*
                     91:  * Baud rates: no 50, 200, or 38400 baud; all other rates are from "Group B".
                     92:  *     EXTA => 19200 baud
                     93:  *     EXTB => 2000 baud
                     94:  */
                     95: char   dhu_speeds[] =
                     96:        { 0, 0, 1, 2, 3, 4, 0, 5, 6, 7, 8, 10, 11, 13, 14, 9 };
                     97: 
                     98: short  dhusoftCAR[NDHU];
                     99: 
                    100: struct tty dhu_tty[NDHULINE];
                    101: int    ndhu = NDHULINE;
                    102: int    dhuact;                         /* mask of active dhu's */
                    103: int    dhustart(), ttrstrt();
                    104: 
                    105: /*
                    106:  * The clist space is mapped by the driver onto each UNIBUS.
                    107:  * The UBACVT macro converts a clist space address for unibus uban
                    108:  * into an i/o space address for the DMA routine.
                    109:  */
                    110: int    dhu_ubinfo[NUBA];       /* info about allocated unibus map */
                    111: int    cbase[NUBA];            /* base address in unibus map */
                    112: #define UBACVT(x, uban)        (cbase[uban] + ((x)-(char *)cfree))
                    113: 
                    114: /*
                    115:  * Routine for configuration to force a dhu to interrupt.
                    116:  */
                    117: /*ARGSUSED*/
                    118: dhuprobe(reg)
                    119:        caddr_t reg;
                    120: {
                    121:        register int br, cvec;          /* these are ``value-result'' */
                    122:        register struct dhudevice *dhuaddr = (struct dhudevice *)reg;
                    123:        int i;
                    124: 
                    125: #ifdef lint
                    126:        br = 0; cvec = br; br = cvec;
                    127:        if (ndhu == 0) ndhu = 1;
                    128:        dhurint(0); dhuxint(0);
                    129: #endif
                    130:        /*
                    131:         * The basic idea here is:
                    132:         *      do a self-test by setting the Master-Reset bit
                    133:         *      if this fails, then return
                    134:         *      if successful, there will be 8 diagnostic codes in RX FIFO
                    135:         *      therefore ask for a  Received-Data-Available interrupt
                    136:         *      wait for it...
                    137:         *      reset the interrupt-enable bit and flush out the diag. codes
                    138:         */
                    139:        dhuaddr->dhucsr = DHU_CS_MCLR;
                    140:        for (i = 0; i < 1000; i++) {
                    141:                DELAY(10000);
                    142:                if ((dhuaddr->dhucsr&DHU_CS_MCLR) == 0)
                    143:                        break;
                    144:        }
                    145:        if (dhuaddr->dhucsr&DHU_CS_MCLR)
                    146:                return(0);
                    147:        if (dhuaddr->dhucsr&DHU_CS_DFAIL)
                    148:                return(0);
                    149:        dhuaddr->dhucsr = DHU_CS_RIE;
                    150:        DELAY(1000);
                    151:        dhuaddr->dhucsr = 0;
                    152:        while (dhuaddr->dhurbuf < 0)
                    153:                /* void */;
                    154:        return (sizeof(struct dhudevice));
                    155: }
                    156: 
                    157: /*
                    158:  * Routine called to attach a dhu.
                    159:  */
                    160: dhuattach(ui)
                    161:        struct uba_device *ui;
                    162: {
                    163: 
                    164:        dhusoftCAR[ui->ui_unit] = ui->ui_flags;
                    165:        cbase[ui->ui_ubanum] = -1;
                    166: }
                    167: 
                    168: /*
                    169:  * Open a DHU11 line, mapping the clist onto the uba if this
                    170:  * is the first dhu on this uba.  Turn on this dhu if this is
                    171:  * the first use of it.
                    172:  */
                    173: /*ARGSUSED*/
                    174: dhuopen(dev, flag)
                    175:        dev_t dev;
                    176: {
                    177:        register struct tty *tp;
                    178:        register int unit, dhu;
                    179:        register struct dhudevice *addr;
                    180:        register struct uba_device *ui;
                    181:        int s;
                    182: 
                    183:        unit = UNIT(dev);
                    184:        dhu = unit >> 4;
                    185:        if (unit >= NDHULINE || (ui = dhuinfo[dhu])== 0 || ui->ui_alive == 0)
                    186:                return (ENXIO);
                    187:        tp = &dhu_tty[unit];
                    188:        if (tp->t_state & TS_XCLUDE && u.u_uid != 0)
                    189:                return (EBUSY);
                    190:        addr = (struct dhudevice *)ui->ui_addr;
                    191:        tp->t_addr = (caddr_t)addr;
                    192:        tp->t_oproc = dhustart;
                    193:        /*
                    194:         * While setting up state for this uba and this dhu,
                    195:         * block uba resets which can clear the state.
                    196:         */
                    197:        s = spl5();
                    198:        if (cbase[ui->ui_ubanum] == -1) {
                    199:                dhu_ubinfo[ui->ui_ubanum] =
                    200:                    uballoc(ui->ui_ubanum, (caddr_t)cfree,
                    201:                        nclist*sizeof(struct cblock), 0);
                    202:                cbase[ui->ui_ubanum] = UBAI_ADDR(dhu_ubinfo[ui->ui_ubanum]);
                    203:        }
                    204:        if ((dhuact&(1<<dhu)) == 0) {
                    205:                addr->dhucsr = DHU_SELECT(0) | DHU_IE;
                    206:                addr->dhutimo = DHU_DEF_TIMO;
                    207:                dhuact |= (1<<dhu);
                    208:                /* anything else to configure whole board */
                    209:        }
                    210:        (void) splx(s);
                    211:        /*
                    212:         * If this is first open, initialize tty state to default.
                    213:         */
                    214:        if ((tp->t_state&TS_ISOPEN) == 0) {
                    215:                ttychars(tp);
                    216: #ifndef PORTSELECTOR
                    217:                if (tp->t_ispeed == 0) {
                    218: #else
                    219:                        tp->t_state |= TS_HUPCLS;
                    220: #endif PORTSELECTOR
                    221:                        tp->t_ispeed = ISPEED;
                    222:                        tp->t_ospeed = ISPEED;
                    223:                        tp->t_flags = IFLAGS;
                    224: #ifndef PORTSELECTOR
                    225:                }
                    226: #endif PORTSELECTOR
                    227:                tp->t_dev = dev;
                    228:                dhuparam(unit);
                    229:        }
                    230:        /*
                    231:         * Wait for carrier, then process line discipline specific open.
                    232:         */
                    233:        s = spl5();
                    234:        if ((dhumctl(dev, DHU_ON, DMSET) & DHU_CAR) ||
                    235:            (dhusoftCAR[dhu] & (1<<(unit&0xf))))
                    236:                tp->t_state |= TS_CARR_ON;
                    237:        while ((tp->t_state & TS_CARR_ON) == 0) {
                    238:                tp->t_state |= TS_WOPEN;
                    239:                sleep((caddr_t)&tp->t_rawq, TTIPRI);
                    240:        }
                    241:        (void) splx(s);
                    242:        return ((*linesw[tp->t_line].l_open)(dev, tp));
                    243: }
                    244: 
                    245: /*
                    246:  * Close a DHU11 line, turning off the modem control.
                    247:  */
                    248: /*ARGSUSED*/
                    249: dhuclose(dev, flag)
                    250:        dev_t dev;
                    251:        int flag;
                    252: {
                    253:        register struct tty *tp;
                    254:        register unit;
                    255: 
                    256:        unit = UNIT(dev);
                    257:        tp = &dhu_tty[unit];
                    258:        (*linesw[tp->t_line].l_close)(tp);
                    259:        (void) dhumctl(unit, DHU_BRK, DMBIC);
                    260:        if ((tp->t_state&(TS_HUPCLS|TS_WOPEN)) || (tp->t_state&TS_ISOPEN)==0)
                    261: #ifdef PORTSELECTOR
                    262:        {
                    263:                extern int wakeup();
                    264: 
                    265:                (void) dhumctl(unit, DHU_OFF, DMSET);
                    266:                /* Hold DTR low for 0.5 seconds */
                    267:                timeout(wakeup, (caddr_t) &tp->t_dev, hz/2);
                    268:                sleep((caddr_t) &tp->t_dev, PZERO);
                    269:        }
                    270: #else
                    271:                (void) dhumctl(unit, DHU_OFF, DMSET);
                    272: #endif PORTSELECTOR
                    273:        ttyclose(tp);
                    274: }
                    275: 
                    276: dhuread(dev, uio)
                    277:        dev_t dev;
                    278:        struct uio *uio;
                    279: {
                    280:        register struct tty *tp = &dhu_tty[UNIT(dev)];
                    281: 
                    282:        return ((*linesw[tp->t_line].l_read)(tp, uio));
                    283: }
                    284: 
                    285: dhuwrite(dev, uio)
                    286:        dev_t dev;
                    287:        struct uio *uio;
                    288: {
                    289:        register struct tty *tp = &dhu_tty[UNIT(dev)];
                    290: 
                    291:        return ((*linesw[tp->t_line].l_write)(tp, uio));
                    292: }
                    293: 
                    294: /*
                    295:  * DHU11 receiver interrupt.
                    296:  */
                    297: dhurint(dhu)
                    298:        int dhu;
                    299: {
                    300:        register struct tty *tp;
                    301:        register c;
                    302:        register struct dhudevice *addr;
                    303:        register struct tty *tp0;
                    304:        register struct uba_device *ui;
                    305:        register line;
                    306:        int overrun = 0;
                    307: 
                    308: #ifdef VAX630
                    309:        (void) spl5();
                    310: #endif
                    311:        ui = dhuinfo[dhu];
                    312:        if (ui == 0 || ui->ui_alive == 0)
                    313:                return;
                    314:        addr = (struct dhudevice *)ui->ui_addr;
                    315:        tp0 = &dhu_tty[dhu<<4];
                    316:        /*
                    317:         * Loop fetching characters from the silo for this
                    318:         * dhu until there are no more in the silo.
                    319:         */
                    320:        while ((c = addr->dhurbuf) < 0) {       /* (c & DHU_RB_VALID) == on */
                    321:                line = DHU_RX_LINE(c);
                    322:                tp = tp0 + line;
                    323:                if ((c & DHU_RB_STAT) == DHU_RB_STAT) {
                    324:                        /*
                    325:                         * modem changed or diag info
                    326:                         */
                    327:                        if (c & DHU_RB_DIAG) {
                    328:                                /* decode diagnostic messages */
                    329:                                continue;
                    330:                        }
                    331:                        if (c & DHU_ST_DCD)
                    332:                                (void)(*linesw[tp->t_line].l_modem)(tp, 1);
                    333:                        else if ((dhusoftCAR[dhu] & (1<<line)) == 0 &&
                    334:                            (*linesw[tp->t_line].l_modem)(tp, 0) == 0)
                    335:                                (void) dhumctl((dhu<<4)|line, DHU_OFF, DMSET);
                    336:                        continue;
                    337:                }
                    338:                if ((tp->t_state&TS_ISOPEN) == 0) {
                    339:                        wakeup((caddr_t)&tp->t_rawq);
                    340: #ifdef PORTSELECTOR
                    341:                        if ((tp->t_state&TS_WOPEN) == 0)
                    342: #endif
                    343:                                continue;
                    344:                }
                    345:                if (c & DHU_RB_PE)
                    346:                        if ((tp->t_flags&(EVENP|ODDP)) == EVENP ||
                    347:                            (tp->t_flags&(EVENP|ODDP)) == ODDP)
                    348:                                continue;
                    349:                if ((c & DHU_RB_DO) && overrun == 0) {
                    350:                        log(LOG_WARNING, "dhu%d: silo overflow\n", dhu);
                    351:                        overrun = 1;
                    352:                }
                    353:                if (c & DHU_RB_FE)
                    354:                        /*
                    355:                         * At framing error (break) generate
                    356:                         * a null (in raw mode, for getty), or a
                    357:                         * interrupt (in cooked/cbreak mode).
                    358:                         */
                    359:                        if (tp->t_flags&RAW)
                    360:                                c = 0;
                    361:                        else
                    362:                                c = tp->t_intrc;
                    363: #if NBK > 0
                    364:                if (tp->t_line == NETLDISC) {
                    365:                        c &= 0x7f;
                    366:                        BKINPUT(c, tp);
                    367:                } else
                    368: #endif
                    369:                        (*linesw[tp->t_line].l_rint)(c, tp);
                    370:        }
                    371: }
                    372: 
                    373: /*
                    374:  * Ioctl for DHU11.
                    375:  */
                    376: /*ARGSUSED*/
                    377: dhuioctl(dev, cmd, data, flag)
                    378:        caddr_t data;
                    379: {
                    380:        register struct tty *tp;
                    381:        register int unit = UNIT(dev);
                    382:        int error;
                    383: 
                    384:        tp = &dhu_tty[unit];
                    385:        error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
                    386:        if (error >= 0)
                    387:                return (error);
                    388:        error = ttioctl(tp, cmd, data, flag);
                    389:        if (error >= 0) {
                    390:                if (cmd == TIOCSETP || cmd == TIOCSETN || cmd == TIOCLSET ||
                    391:                    cmd == TIOCLBIC || cmd == TIOCLBIS)
                    392:                        dhuparam(unit);
                    393:                return (error);
                    394:        }
                    395: 
                    396:        switch (cmd) {
                    397:        case TIOCSBRK:
                    398:                (void) dhumctl(unit, DHU_BRK, DMBIS);
                    399:                break;
                    400: 
                    401:        case TIOCCBRK:
                    402:                (void) dhumctl(unit, DHU_BRK, DMBIC);
                    403:                break;
                    404: 
                    405:        case TIOCSDTR:
                    406:                (void) dhumctl(unit, DHU_DTR|DHU_RTS, DMBIS);
                    407:                break;
                    408: 
                    409:        case TIOCCDTR:
                    410:                (void) dhumctl(unit, DHU_DTR|DHU_RTS, DMBIC);
                    411:                break;
                    412: 
                    413:        case TIOCMSET:
                    414:                (void) dhumctl(dev, dmtodhu(*(int *)data), DMSET);
                    415:                break;
                    416: 
                    417:        case TIOCMBIS:
                    418:                (void) dhumctl(dev, dmtodhu(*(int *)data), DMBIS);
                    419:                break;
                    420: 
                    421:        case TIOCMBIC:
                    422:                (void) dhumctl(dev, dmtodhu(*(int *)data), DMBIC);
                    423:                break;
                    424: 
                    425:        case TIOCMGET:
                    426:                *(int *)data = dhutodm(dhumctl(dev, 0, DMGET));
                    427:                break;
                    428:        default:
                    429:                return (ENOTTY);
                    430:        }
                    431:        return (0);
                    432: }
                    433: 
                    434: dmtodhu(bits)
                    435:        register int bits;
                    436: {
                    437:        register int b = 0;
                    438: 
                    439:        if (bits & DML_RTS) b |= DHU_RTS;
                    440:        if (bits & DML_DTR) b |= DHU_DTR;
                    441:        if (bits & DML_LE) b |= DHU_LE;
                    442:        return(b);
                    443: }
                    444: 
                    445: dhutodm(bits)
                    446:        register int bits;
                    447: {
                    448:        register int b = 0;
                    449: 
                    450:        if (bits & DHU_DSR) b |= DML_DSR;
                    451:        if (bits & DHU_RNG) b |= DML_RNG;
                    452:        if (bits & DHU_CAR) b |= DML_CAR;
                    453:        if (bits & DHU_CTS) b |= DML_CTS;
                    454:        if (bits & DHU_RTS) b |= DML_RTS;
                    455:        if (bits & DHU_DTR) b |= DML_DTR;
                    456:        if (bits & DHU_LE) b |= DML_LE;
                    457:        return(b);
                    458: }
                    459: 
                    460: 
                    461: /*
                    462:  * Set parameters from open or stty into the DHU hardware
                    463:  * registers.
                    464:  */
                    465: dhuparam(unit)
                    466:        register int unit;
                    467: {
                    468:        register struct tty *tp;
                    469:        register struct dhudevice *addr;
                    470:        register int lpar;
                    471:        int s;
                    472: 
                    473:        tp = &dhu_tty[unit];
                    474:        addr = (struct dhudevice *)tp->t_addr;
                    475:        /*
                    476:         * Block interrupts so parameters will be set
                    477:         * before the line interrupts.
                    478:         */
                    479:        s = spl5();
                    480:        if ((tp->t_ispeed) == 0) {
                    481:                tp->t_state |= TS_HUPCLS;
                    482:                (void)dhumctl(unit, DHU_OFF, DMSET);
                    483:                splx(s);
                    484:                return;
                    485:        }
                    486:        lpar = (dhu_speeds[tp->t_ospeed]<<12) | (dhu_speeds[tp->t_ispeed]<<8);
                    487:        if ((tp->t_ispeed) == B134)
                    488:                lpar |= DHU_LP_BITS6|DHU_LP_PENABLE;
                    489:        else if (tp->t_flags & (RAW|LITOUT|PASS8))
                    490:                lpar |= DHU_LP_BITS8;
                    491:        else
                    492:                lpar |= DHU_LP_BITS7|DHU_LP_PENABLE;
                    493:        if (tp->t_flags&EVENP)
                    494:                lpar |= DHU_LP_EPAR;
                    495:        if ((tp->t_ospeed) == B110)
                    496:                lpar |= DHU_LP_TWOSB;
                    497:        addr->dhucsr = DHU_SELECT(unit) | DHU_IE;
                    498:        addr->dhulpr = lpar;
                    499:        splx(s);
                    500: }
                    501: 
                    502: /*
                    503:  * DHU11 transmitter interrupt.
                    504:  * Restart each line which used to be active but has
                    505:  * terminated transmission since the last interrupt.
                    506:  */
                    507: dhuxint(dhu)
                    508:        int dhu;
                    509: {
                    510:        register struct tty *tp;
                    511:        register struct dhudevice *addr;
                    512:        register struct tty *tp0;
                    513:        register struct uba_device *ui;
                    514:        register int line, t;
                    515:        u_short cntr;
                    516: 
                    517: #ifdef VAX630
                    518:        (void) spl5();
                    519: #endif
                    520:        ui = dhuinfo[dhu];
                    521:        tp0 = &dhu_tty[dhu<<4];
                    522:        addr = (struct dhudevice *)ui->ui_addr;
                    523:        while ((t = addr->dhucsrh) & DHU_CSH_TI) {
                    524:                line = DHU_TX_LINE(t);
                    525:                tp = tp0 + line;
                    526:                tp->t_state &= ~TS_BUSY;
                    527:                if (t & DHU_CSH_NXM) {
                    528:                        printf("dhu(%d,%d): NXM fault\n", dhu, line);
                    529:                        /* SHOULD RESTART OR SOMETHING... */
                    530:                }
                    531:                if (tp->t_state&TS_FLUSH)
                    532:                        tp->t_state &= ~TS_FLUSH;
                    533:                else {
                    534:                        addr->dhucsrl = DHU_SELECT(line) | DHU_IE;
                    535:                        /*
                    536:                         * Do arithmetic in a short to make up
                    537:                         * for lost 16&17 bits.
                    538:                         */
                    539:                        cntr = addr->dhubar1 -
                    540:                            UBACVT(tp->t_outq.c_cf, ui->ui_ubanum);
                    541:                        ndflush(&tp->t_outq, (int)cntr);
                    542:                }
                    543:                if (tp->t_line)
                    544:                        (*linesw[tp->t_line].l_start)(tp);
                    545:                else
                    546:                        dhustart(tp);
                    547:        }
                    548: }
                    549: 
                    550: /*
                    551:  * Start (restart) transmission on the given DHU11 line.
                    552:  */
                    553: dhustart(tp)
                    554:        register struct tty *tp;
                    555: {
                    556:        register struct dhudevice *addr;
                    557:        register int car, dhu, unit, nch;
                    558:        int s;
                    559: 
                    560:        unit = minor(tp->t_dev);
                    561:        dhu = unit >> 4;
                    562:        unit &= 0xf;
                    563:        addr = (struct dhudevice *)tp->t_addr;
                    564: 
                    565:        /*
                    566:         * Must hold interrupts in following code to prevent
                    567:         * state of the tp from changing.
                    568:         */
                    569:        s = spl5();
                    570:        /*
                    571:         * If it's currently active, or delaying, no need to do anything.
                    572:         */
                    573:        if (tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
                    574:                goto out;
                    575:        /*
                    576:         * If there are sleepers, and output has drained below low
                    577:         * water mark, wake up the sleepers..
                    578:         */
                    579:        if (tp->t_outq.c_cc<=TTLOWAT(tp)) {
                    580:                if (tp->t_state&TS_ASLEEP) {
                    581:                        tp->t_state &= ~TS_ASLEEP;
                    582:                        wakeup((caddr_t)&tp->t_outq);
                    583:                }
                    584:                if (tp->t_wsel) {
                    585:                        selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
                    586:                        tp->t_wsel = 0;
                    587:                        tp->t_state &= ~TS_WCOLL;
                    588:                }
                    589:        }
                    590:        /*
                    591:         * Now restart transmission unless the output queue is
                    592:         * empty.
                    593:         */
                    594:        if (tp->t_outq.c_cc == 0)
                    595:                goto out;
                    596:        if (tp->t_flags & (RAW|LITOUT))
                    597:                nch = ndqb(&tp->t_outq, 0);
                    598:        else {
                    599:                nch = ndqb(&tp->t_outq, 0200);
                    600:                /*
                    601:                 * If first thing on queue is a delay process it.
                    602:                 */
                    603:                if (nch == 0) {
                    604:                        nch = getc(&tp->t_outq);
                    605:                        timeout(ttrstrt, (caddr_t)tp, (nch&0x7f)+6);
                    606:                        tp->t_state |= TS_TIMEOUT;
                    607:                        goto out;
                    608:                }
                    609:        }
                    610:        /*
                    611:         * If characters to transmit, restart transmission.
                    612:         */
                    613:        if (nch) {
                    614:                car = UBACVT(tp->t_outq.c_cf, dhuinfo[dhu]->ui_ubanum);
                    615:                addr->dhucsrl = DHU_SELECT(unit) | DHU_IE;
                    616:                addr->dhulcr &= ~DHU_LC_TXABORT;
                    617:                addr->dhubcr = nch;
                    618:                addr->dhubar1 = car;
                    619:                addr->dhubar2 = ((car >> DHU_XBA_SHIFT) & DHU_BA2_XBA) |
                    620:                                        DHU_BA2_DMAGO;
                    621:                tp->t_state |= TS_BUSY;
                    622:        }
                    623: out:
                    624:        splx(s);
                    625: }
                    626: 
                    627: /*
                    628:  * Stop output on a line, e.g. for ^S/^Q or output flush.
                    629:  */
                    630: /*ARGSUSED*/
                    631: dhustop(tp, flag)
                    632:        register struct tty *tp;
                    633: {
                    634:        register struct dhudevice *addr;
                    635:        register int unit, s;
                    636: 
                    637:        addr = (struct dhudevice *)tp->t_addr;
                    638:        /*
                    639:         * Block input/output interrupts while messing with state.
                    640:         */
                    641:        s = spl5();
                    642:        if (tp->t_state & TS_BUSY) {
                    643:                /*
                    644:                 * Device is transmitting; stop output
                    645:                 * by selecting the line and setting the
                    646:                 * abort xmit bit.  We will get an xmit interrupt,
                    647:                 * where we will figure out where to continue the
                    648:                 * next time the transmitter is enabled.  If
                    649:                 * TS_FLUSH is set, the outq will be flushed.
                    650:                 * In either case, dhustart will clear the TXABORT bit.
                    651:                 */
                    652:                unit = minor(tp->t_dev);
                    653:                addr->dhucsrl = DHU_SELECT(unit) | DHU_IE;
                    654:                addr->dhulcr |= DHU_LC_TXABORT;
                    655:                if ((tp->t_state&TS_TTSTOP)==0)
                    656:                        tp->t_state |= TS_FLUSH;
                    657:        }
                    658:        (void) splx(s);
                    659: }
                    660: 
                    661: /*
                    662:  * DHU11 modem control
                    663:  */
                    664: dhumctl(dev, bits, how)
                    665:        dev_t dev;
                    666:        int bits, how;
                    667: {
                    668:        register struct dhudevice *dhuaddr;
                    669:        register int unit, mbits;
                    670:        int s;
                    671: 
                    672:        unit = UNIT(dev);
                    673:        dhuaddr = (struct dhudevice *)(dhu_tty[unit].t_addr);
                    674:        unit &= 0xf;
                    675:        s = spl5();
                    676:        dhuaddr->dhucsr = DHU_SELECT(unit) | DHU_IE;
                    677:        /*
                    678:         * combine byte from stat register (read only, bits 16..23)
                    679:         * with lcr register (read write, bits 0..15).
                    680:         */
                    681:        mbits = dhuaddr->dhulcr | (dhuaddr->dhustat << 16);
                    682:        switch (how) {
                    683:        case DMSET:
                    684:                mbits = (mbits & 0xff0000) | bits;
                    685:                break;
                    686: 
                    687:        case DMBIS:
                    688:                mbits |= bits;
                    689:                break;
                    690: 
                    691:        case DMBIC:
                    692:                mbits &= ~bits;
                    693:                break;
                    694: 
                    695:        case DMGET:
                    696:                (void) splx(s);
                    697:                return(mbits);
                    698:        }
                    699:        dhuaddr->dhulcr = (mbits & 0xffff) | DHU_LC_RXEN;
                    700:        dhuaddr->dhulcr2 = DHU_LC2_TXEN;
                    701:        (void) splx(s);
                    702:        return(mbits);
                    703: }
                    704: 
                    705: /*
                    706:  * Reset state of driver if UBA reset was necessary.
                    707:  * Reset the line and modem control registers.
                    708:  * restart transmitters.
                    709:  */
                    710: dhureset(uban)
                    711:        int uban;
                    712: {
                    713:        register int dhu, unit;
                    714:        register struct tty *tp;
                    715:        register struct uba_device *ui;
                    716:        register struct dhudevice *addr;
                    717:        int i;
                    718: 
                    719:        for (dhu = 0; dhu < NDHU; dhu++) {
                    720:                ui = dhuinfo[dhu];
                    721:                if (ui == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban)
                    722:                        continue;
                    723:                printf(" dhu%d", dhu);
                    724:                if (dhu_ubinfo[uban]) {
                    725:                        dhu_ubinfo[uban] = uballoc(uban, (caddr_t)cfree,
                    726:                                            nclist*sizeof (struct cblock), 0);
                    727:                        cbase[uban] = UBAI_ADDR(dhu_ubinfo[uban]);
                    728:                }
                    729:                addr = (struct dhudevice *)ui->ui_addr;
                    730:                addr->dhucsr = DHU_SELECT(0) | DHU_IE;
                    731:                addr->dhutimo = DHU_DEF_TIMO;
                    732:                unit = dhu * 16;
                    733:                for (i = 0; i < 16; i++) {
                    734:                        tp = &dhu_tty[unit];
                    735:                        if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) {
                    736:                                dhuparam(unit);
                    737:                                (void)dhumctl(unit, DHU_ON, DMSET);
                    738:                                tp->t_state &= ~TS_BUSY;
                    739:                                dhustart(tp);
                    740:                        }
                    741:                        unit++;
                    742:                }
                    743:        }
                    744: }
                    745: #endif

unix.superglobalmegacorp.com

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