Annotation of 43BSDReno/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.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.