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

unix.superglobalmegacorp.com

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