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

1.1       root        1: /*
                      2:  * Copyright (c) 1982, 1986 Regents of the University of California.
                      3:  * All rights reserved.  The Berkeley software License Agreement
                      4:  * specifies the terms and conditions for redistribution.
                      5:  *
                      6:  *     @(#)dmf.c       7.1 (Berkeley) 6/5/86
                      7:  */
                      8: 
                      9: #include "dmf.h"
                     10: #if NDMF > 0
                     11: /*
                     12:  * DMF32 driver
                     13:  *
                     14:  *
                     15:  * TODO:
                     16:  *     test with modem
                     17:  *     load as much as possible into silo
                     18:  *     use auto XON/XOFF
                     19:  *     test reset code
                     20:  ****************************
                     21:  * DMF32 line printer driver
                     22:  *
                     23:  * the line printer on dmfx is indicated by a minor device code of 128+x
                     24:  *
                     25:  * the flags field of the config file is interpreted like so:
                     26:  * bits                meaning
                     27:  * ----                -------
                     28:  * 0-7         soft carrier bits for ttys part of dmf32
                     29:  * 8-15                number of cols/line on the line printer
                     30:  *                     if 0, 132 will be used.
                     31:  * 16-23       number of lines/page on the line printer
                     32:  *                     if 0, 66 will be used.
                     33:  * 24          if 1 DO NOT use the auto format mode of the
                     34:  *                     line printer parallel port
                     35:  */
                     36: #include "../machine/pte.h"
                     37: 
                     38: #include "bk.h"
                     39: #include "uba.h"
                     40: #include "param.h"
                     41: #include "conf.h"
                     42: #include "dir.h"
                     43: #include "user.h"
                     44: #include "proc.h"
                     45: #include "ioctl.h"
                     46: #include "tty.h"
                     47: #include "map.h"
                     48: #include "buf.h"
                     49: #include "vm.h"
                     50: #include "bkmac.h"
                     51: #include "clist.h"
                     52: #include "file.h"
                     53: #include "uio.h"
                     54: #include "kernel.h"
                     55: #include "syslog.h"
                     56: 
                     57: #include "ubareg.h"
                     58: #include "ubavar.h"
                     59: #include "dmfreg.h"
                     60: 
                     61: /*
                     62:  * Definition of the driver for the auto-configuration program.
                     63:  */
                     64: int    dmfprobe(), dmfattach(), dmfrint(), dmfxint();
                     65: int    dmflint();
                     66: struct uba_device *dmfinfo[NDMF];
                     67: u_short        dmfstd[] = { 0 };
                     68: struct uba_driver dmfdriver =
                     69:        { dmfprobe, 0, dmfattach, 0, dmfstd, "dmf", dmfinfo };
                     70: 
                     71: int    dmf_timeout = 10;               /* silo timeout, in ms */
                     72: int    dmf_mindma = 4;                 /* don't dma below this point */
                     73: 
                     74: /*
                     75:  * Local variables for the driver
                     76:  */
                     77: char   dmf_speeds[] =
                     78:        { 0, 0, 1, 2, 3, 4, 0, 5, 6, 7, 010, 012, 014, 016, 017, 0 };
                     79: 
                     80: #ifndef        PORTSELECTOR
                     81: #define        ISPEED  B9600
                     82: #define        IFLAGS  (EVENP|ODDP|ECHO)
                     83: #else
                     84: #define        ISPEED  B4800
                     85: #define        IFLAGS  (EVENP|ODDP)
                     86: #endif
                     87: 
                     88: struct tty dmf_tty[NDMF*8];
                     89: char   dmfsoftCAR[NDMF];
                     90: 
                     91: struct dmfl_softc {
                     92:        u_int   dmfl_state;             /* soft state bits */
                     93:        int     dmfl_info;              /* uba info */
                     94:        u_short dmfl_lines;             /* lines per page (66 def.) */
                     95:        u_short dmfl_cols;              /* cols per line (132 def.) */
                     96:        u_short dmfl_format;            /* fflag for auto form feed */
                     97:        char    dmfl_buf[DMFL_BUFSIZ];
                     98: } dmfl_softc[NDMF];
                     99: 
                    100: /*
                    101:  * convert device number into DMF line printer unit number
                    102:  */
                    103: #define        DMFL_UNIT(d)    (minor(d)&0xF)  /* up to 16 DMFs */
                    104: 
                    105: #define ASLP 1         /* waiting for interrupt from dmf */
                    106: #define OPEN 2         /* line printer is open */
                    107: #define ERROR 4                /* error while printing, driver
                    108:                         refuses to do anything till closed */
                    109: #define MOREIO 8       /* more data for printer */
                    110: 
                    111: #ifndef lint
                    112: int    ndmf = NDMF*8;                  /* used by iostat */
                    113: #endif
                    114: int    dmfact;                         /* mask of active dmf's */
                    115: int    dmfstart(), ttrstrt();
                    116: 
                    117: /*
                    118:  * The clist space is mapped by the driver onto each UNIBUS.
                    119:  * The UBACVT macro converts a clist space address for unibus uban
                    120:  * into an i/o space address for the DMA routine.
                    121:  */
                    122: int    dmf_ubinfo[NUBA];               /* info about allocated unibus map */
                    123: int    cbase[NUBA];                    /* base address in unibus map */
                    124: #define        UBACVT(x, uban)         (cbase[uban] + ((x)-(char *)cfree))
                    125: char   dmf_dma[NDMF*8];
                    126: 
                    127: /*
                    128:  * Routine for configuration to set dmf interrupt.
                    129:  */
                    130: /*ARGSUSED*/
                    131: dmfprobe(reg, ctlr)
                    132:        caddr_t reg;
                    133:        struct uba_device *ctlr;
                    134: {
                    135:        register int br, cvec;          /* these are ``value-result'' */
                    136:        register struct dmfdevice *dmfaddr = (struct dmfdevice *)reg;
                    137:        register int i;
                    138:        register unsigned int a;
                    139:        static char *dmfdevs[]=
                    140:                {"parallel","printer","synch","asynch"};
                    141:        unsigned int dmfoptions;
                    142:        static int (*intrv[3])() = { (int (*)())0, (int (*)())0, (int (*)())0 };
                    143: 
                    144: #ifdef lint
                    145:        br = 0; cvec = br; br = cvec;
                    146:        dmfxint(0); dmfrint(0);
                    147:        dmfsrint(); dmfsxint(); dmfdaint(); dmfdbint(); dmflint(0);
                    148: #endif
                    149:        /*
                    150:         * Pick the usual size DMF vector here (don't decrement it here).
                    151:         * grab configuration; note that the DMF32
                    152:         * doesn't seem to put the right bits in this
                    153:         * register until AFTER the interrupt vector is set.
                    154:         */
                    155:        br = 0x15;
                    156:        cvec = (uba_hd[numuba].uh_lastiv - 4*8);
                    157:        dmfaddr->dmfccsr0 = (cvec >> 2);
                    158:        dmfoptions = dmfaddr->dmfccsr0 & DMFC_CONFMASK;
                    159: 
                    160:        /* catch a couple of special cases:  Able vmz/32n and vmz/lp    */
                    161:        if (dmfoptions == DMFC_ASYNC) {
                    162:                /* Async portion only */
                    163: 
                    164:                cvec = (uba_hd[numuba].uh_lastiv -= 8);
                    165:                dmfaddr->dmfccsr0 = (cvec - 2*8) >> 2;
                    166:                intrv[0] = ctlr->ui_intr[4];
                    167:                intrv[1] = ctlr->ui_intr[5];
                    168:                ctlr->ui_intr = intrv;
                    169:        } else if (dmfoptions == DMFC_LP) {
                    170:                /* LP portion only */
                    171: 
                    172:                cvec = (uba_hd[numuba].uh_lastiv -= 8);
                    173:                ctlr->ui_intr = &ctlr->ui_intr[6];
                    174:        } else if (dmfoptions == (DMFC_LP|DMFC_ASYNC)) {
                    175:                /* LP ans Async portions only */
                    176: 
                    177:                cvec = (uba_hd[numuba].uh_lastiv -= 2*8);
                    178:                ctlr->ui_intr = &ctlr->ui_intr[4];
                    179:        } else {
                    180:                /* All other configurations get everything */
                    181: 
                    182:                cvec = (uba_hd[numuba].uh_lastiv -= 4*8);
                    183:        }
                    184:        a = (dmfoptions >> 12) & 0xf;
                    185:        printf("dmf%d:", ctlr->ui_unit);
                    186:        for (i = 0; a != 0; ++i, a >>= 1) {
                    187:                if (a & 1)
                    188:                        printf(" %s",dmfdevs[i]);
                    189:        }
                    190:        printf(".\n");
                    191: 
                    192:        if (dmfoptions & DMFC_LP)
                    193:                dmfaddr->dmfl_ctrl = DMFL_RESET;
                    194:        return (sizeof (struct dmfdevice));
                    195: }
                    196: 
                    197: /*
                    198:  * Routine called to attach a dmf.
                    199:  */
                    200: dmfattach(ui)
                    201:        struct uba_device *ui;
                    202: {
                    203:        register int cols = (ui->ui_flags>>8) & 0xff;
                    204:        register int lines = (ui->ui_flags>>16) & 0xff;
                    205: 
                    206:        dmfsoftCAR[ui->ui_unit] = ui->ui_flags & 0xff;
                    207:        dmfl_softc[ui->ui_unit].dmfl_cols = cols == 0 ? DMFL_DEFCOLS : cols;
                    208:        dmfl_softc[ui->ui_unit].dmfl_lines = lines == 0 ? DMFL_DEFLINES : lines;
                    209:        if ((ui->ui_flags >> 24) & 0x1)
                    210:                dmfl_softc[ui->ui_unit].dmfl_format = (2 << 8);
                    211:        else
                    212:                dmfl_softc[ui->ui_unit].dmfl_format = (2 << 8) | DMFL_FORMAT;
                    213:        cbase[ui->ui_ubanum] = -1;
                    214: }
                    215: 
                    216: 
                    217: /*
                    218:  * Open a DMF32 line, mapping the clist onto the uba if this
                    219:  * is the first dmf on this uba.  Turn on this dmf if this is
                    220:  * the first use of it.
                    221:  */
                    222: /*ARGSUSED*/
                    223: dmfopen(dev, flag)
                    224:        dev_t dev;
                    225: {
                    226:        register struct tty *tp;
                    227:        register int unit, dmf;
                    228:        register struct dmfdevice *addr;
                    229:        register struct uba_device *ui;
                    230:        int s;
                    231: 
                    232:        unit = minor(dev);
                    233:        if (unit & 0200)
                    234:                return (dmflopen(dev,flag));
                    235:        dmf = unit >> 3;
                    236:        if (unit >= NDMF*8 || (ui = dmfinfo[dmf])== 0 || ui->ui_alive == 0)
                    237:                return (ENXIO);
                    238:        tp = &dmf_tty[unit];
                    239:        if (tp->t_state&TS_XCLUDE && u.u_uid!=0)
                    240:                return (EBUSY);
                    241:        addr = (struct dmfdevice *)ui->ui_addr;
                    242:        tp->t_addr = (caddr_t)addr;
                    243:        tp->t_oproc = dmfstart;
                    244:        tp->t_state |= TS_WOPEN;
                    245:        /*
                    246:         * While setting up state for this uba and this dmf,
                    247:         * block uba resets which can clear the state.
                    248:         */
                    249:        s = spltty();
                    250:        if (cbase[ui->ui_ubanum] == -1) {
                    251:                dmf_ubinfo[ui->ui_ubanum] =
                    252:                    uballoc(ui->ui_ubanum, (caddr_t)cfree,
                    253:                        nclist*sizeof(struct cblock), 0);
                    254:                cbase[ui->ui_ubanum] = UBAI_ADDR(dmf_ubinfo[ui->ui_ubanum]);
                    255:        }
                    256:        if ((dmfact&(1<<dmf)) == 0) {
                    257:                addr->dmfcsr |= DMF_IE;
                    258:                dmfact |= (1<<dmf);
                    259:                addr->dmfrsp = dmf_timeout;
                    260:        }
                    261:        splx(s);
                    262:        /*
                    263:         * If this is first open, initialize tty state to default.
                    264:         */
                    265:        if ((tp->t_state&TS_ISOPEN) == 0) {
                    266:                ttychars(tp);
                    267: #ifndef PORTSELECTOR
                    268:                if (tp->t_ispeed == 0) {
                    269: #else
                    270:                        tp->t_state |= TS_HUPCLS;
                    271: #endif PORTSELECTOR
                    272:                        tp->t_ispeed = ISPEED;
                    273:                        tp->t_ospeed = ISPEED;
                    274:                        tp->t_flags = IFLAGS;
                    275: #ifndef PORTSELECTOR
                    276:                }
                    277: #endif PORTSELECTOR
                    278:                dmfparam(unit);
                    279:        }
                    280:        /*
                    281:         * Wait for carrier, then process line discipline specific open.
                    282:         */
                    283:        s = spltty();
                    284:        for (;;) {
                    285:                if ((dmfmctl(dev, DMF_ON, DMSET) & (DMF_CAR<<8)) ||
                    286:                    (dmfsoftCAR[dmf] & (1<<(unit&07))))
                    287:                        tp->t_state |= TS_CARR_ON;
                    288:                if (tp->t_state & TS_CARR_ON)
                    289:                        break;
                    290:                tp->t_state |= TS_WOPEN;
                    291:                sleep((caddr_t)&tp->t_rawq, TTIPRI);
                    292:        }
                    293:        splx(s);
                    294:        return ((*linesw[tp->t_line].l_open)(dev, tp));
                    295: }
                    296: 
                    297: /*
                    298:  * Close a DMF32 line.
                    299:  */
                    300: /*ARGSUSED*/
                    301: dmfclose(dev, flag)
                    302:        dev_t dev;
                    303:        int flag;
                    304: {
                    305:        register struct tty *tp;
                    306:        register unit;
                    307: 
                    308:        unit = minor(dev);
                    309:        if (unit & 0200) {
                    310:                dmflclose(dev,flag);
                    311:                return;
                    312:        }
                    313:                
                    314:        tp = &dmf_tty[unit];
                    315:        (*linesw[tp->t_line].l_close)(tp);
                    316:        (void) dmfmctl(unit, DMF_BRK, DMBIC);
                    317:        if (tp->t_state&TS_HUPCLS || (tp->t_state&TS_ISOPEN)==0)
                    318:                (void) dmfmctl(unit, DMF_OFF, DMSET);
                    319:        ttyclose(tp);
                    320: }
                    321: 
                    322: dmfread(dev, uio)
                    323:        dev_t dev;
                    324:        struct uio *uio;
                    325: {
                    326:        register struct tty *tp;
                    327: 
                    328:        if (minor(dev) & 0200)
                    329:                return(ENXIO);
                    330:        tp = &dmf_tty[minor(dev)];
                    331:        return ((*linesw[tp->t_line].l_read)(tp, uio));
                    332: }
                    333: 
                    334: dmfwrite(dev, uio)
                    335:        dev_t dev;
                    336:        struct uio *uio;
                    337: {
                    338:        register struct tty *tp;
                    339: 
                    340:        if (minor(dev) & 0200)
                    341:                return (dmflwrite(dev,uio));
                    342:        tp = &dmf_tty[minor(dev)];
                    343:        return ((*linesw[tp->t_line].l_write)(tp, uio));
                    344: }
                    345: 
                    346: /*
                    347:  * DMF32 receiver interrupt.
                    348:  */
                    349: dmfrint(dmf)
                    350:        int dmf;
                    351: {
                    352:        register c;
                    353:        register struct tty *tp;
                    354:        register struct dmfdevice *addr;
                    355:        register struct tty *tp0;
                    356:        int unit;
                    357:        int overrun = 0;
                    358:        register struct uba_device *ui;
                    359: 
                    360:        ui = dmfinfo[dmf];
                    361:        if (ui == 0 || ui->ui_alive == 0)
                    362:                return;
                    363:        addr = (struct dmfdevice *)ui->ui_addr;
                    364:        tp0 = &dmf_tty[dmf * 8];
                    365:        /*
                    366:         * Loop fetching characters from the silo for this
                    367:         * dmf until there are no more in the silo.
                    368:         */
                    369:        while ((c = addr->dmfrbuf) < 0) {
                    370: 
                    371:                unit = (c >> 8) & 07;
                    372:                tp = tp0 + unit;
                    373:                if (c & DMF_DSC) {
                    374:                        addr->dmfcsr = DMF_IE | DMFIR_TBUF | unit;
                    375:                        if (addr->dmfrms & DMF_CAR)
                    376:                                (void)(*linesw[tp->t_line].l_modem)(tp, 1);
                    377:                        else if ((dmfsoftCAR[dmf] & (1 << unit)) == 0 &&
                    378:                            (*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
                    379:                                addr->dmfcsr = DMF_IE | DMFIR_LCR | unit;
                    380:                                addr->dmflctms = DMFLCR_ENA;
                    381:                        }
                    382:                        continue;
                    383:                }
                    384:                if ((tp->t_state&TS_ISOPEN) == 0) {
                    385:                        wakeup((caddr_t)&tp->t_rawq);
                    386: #ifdef PORTSELECTOR
                    387:                        if ((tp->t_state & TS_WOPEN) == 0)
                    388: #endif
                    389:                                continue;
                    390:                }
                    391:                if (c & (DMF_PE|DMF_DO|DMF_FE)) {
                    392:                        if (c & DMF_PE)
                    393:                                if ((tp->t_flags & (EVENP|ODDP)) == EVENP
                    394:                                || (tp->t_flags & (EVENP|ODDP)) == ODDP)
                    395:                                        continue;
                    396:                        if ((c & DMF_DO) && overrun == 0) {
                    397:                                log(LOG_WARNING, "dmf%d: silo overflow\n", dmf);
                    398:                                overrun = 1;
                    399:                        }
                    400:                        if (c & DMF_FE)
                    401:                                /*
                    402:                                * At framing error (break) generate
                    403:                                * a null (in raw mode, for getty), or a
                    404:                                * interrupt (in cooked/cbreak mode).
                    405:                                */
                    406:                                if (tp->t_flags & RAW)
                    407:                                        c = 0;
                    408:                                else
                    409:                                        c = tp->t_intrc;
                    410:                }
                    411: #if NBK > 0
                    412:                if (tp->t_line == NETLDISC) {
                    413:                        c &= 0177;
                    414:                        BKINPUT(c, tp);
                    415:                } else
                    416: #endif
                    417:                        (*linesw[tp->t_line].l_rint)(c, tp);
                    418:        }
                    419: }
                    420: 
                    421: /*
                    422:  * Ioctl for DMF32.
                    423:  */
                    424: /*ARGSUSED*/
                    425: dmfioctl(dev, cmd, data, flag)
                    426:        dev_t dev;
                    427:        caddr_t data;
                    428: {
                    429:        register struct tty *tp;
                    430:        register int unit = minor(dev);
                    431:        int error;
                    432:  
                    433:        if (unit & 0200)
                    434:                return (ENOTTY);
                    435:        tp = &dmf_tty[unit];
                    436:        error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
                    437:        if (error >= 0)
                    438:                return (error);
                    439:        error = ttioctl(tp, cmd, data, flag);
                    440:        if (error >= 0) {
                    441:                if (cmd == TIOCSETP || cmd == TIOCSETN || cmd == TIOCLBIS ||
                    442:                    cmd == TIOCLBIC || cmd == TIOCLSET)
                    443:                        dmfparam(unit);
                    444:                return (error);
                    445:        }
                    446:        switch (cmd) {
                    447: 
                    448:        case TIOCSBRK:
                    449:                (void) dmfmctl(dev, DMF_BRK, DMBIS);
                    450:                break;
                    451: 
                    452:        case TIOCCBRK:
                    453:                (void) dmfmctl(dev, DMF_BRK, DMBIC);
                    454:                break;
                    455: 
                    456:        case TIOCSDTR:
                    457:                (void) dmfmctl(dev, DMF_DTR|DMF_RTS, DMBIS);
                    458:                break;
                    459: 
                    460:        case TIOCCDTR:
                    461:                (void) dmfmctl(dev, DMF_DTR|DMF_RTS, DMBIC);
                    462:                break;
                    463: 
                    464:        case TIOCMSET:
                    465:                (void) dmfmctl(dev, dmtodmf(*(int *)data), DMSET);
                    466:                break;
                    467: 
                    468:        case TIOCMBIS:
                    469:                (void) dmfmctl(dev, dmtodmf(*(int *)data), DMBIS);
                    470:                break;
                    471: 
                    472:        case TIOCMBIC:
                    473:                (void) dmfmctl(dev, dmtodmf(*(int *)data), DMBIC);
                    474:                break;
                    475: 
                    476:        case TIOCMGET:
                    477:                *(int *)data = dmftodm(dmfmctl(dev, 0, DMGET));
                    478:                break;
                    479: 
                    480:        default:
                    481:                return (ENOTTY);
                    482:        }
                    483:        return (0);
                    484: }
                    485: 
                    486: dmtodmf(bits)
                    487:        register int bits;
                    488: {
                    489:        register int b;
                    490: 
                    491:        b = bits & 012;
                    492:        if (bits & DML_ST) b |= DMF_RATE;
                    493:        if (bits & DML_RTS) b |= DMF_RTS;
                    494:        if (bits & DML_USR) b |= DMF_USRW;
                    495:        return(b);
                    496: }
                    497: 
                    498: dmftodm(bits)
                    499:        register int bits;
                    500: {
                    501:        register int b;
                    502: 
                    503:        b = (bits & 012) | ((bits >> 7) & 0760) | DML_LE;
                    504:        if (bits & DMF_USRR) b |= DML_USR;
                    505:        if (bits & DMF_RTS) b |= DML_RTS;
                    506:        return(b);
                    507: }
                    508:  
                    509: 
                    510: /*
                    511:  * Set parameters from open or stty into the DMF hardware
                    512:  * registers.
                    513:  */
                    514: dmfparam(unit)
                    515:        register int unit;
                    516: {
                    517:        register struct tty *tp;
                    518:        register struct dmfdevice *addr;
                    519:        register int lpar, lcr;
                    520:        int s;
                    521: 
                    522:        tp = &dmf_tty[unit];
                    523:        addr = (struct dmfdevice *)tp->t_addr;
                    524:        /*
                    525:         * Block interrupts so parameters will be set
                    526:         * before the line interrupts.
                    527:         */
                    528:        s = spltty();
                    529:        addr->dmfcsr = (unit&07) | DMFIR_LCR | DMF_IE;
                    530:        if ((tp->t_ispeed)==0) {
                    531:                tp->t_state |= TS_HUPCLS;
                    532:                (void) dmfmctl(unit, DMF_OFF, DMSET);
                    533:                splx(s);
                    534:                return;
                    535:        }
                    536:        lpar = (dmf_speeds[tp->t_ospeed]<<12) | (dmf_speeds[tp->t_ispeed]<<8);
                    537:        lcr = DMFLCR_ENA;
                    538:        if ((tp->t_ispeed) == B134)
                    539:                lpar |= BITS6|PENABLE;
                    540:        else if (tp->t_flags & (RAW|LITOUT|PASS8))
                    541:                lpar |= BITS8;
                    542:        else {
                    543:                lpar |= BITS7|PENABLE;
                    544:                /* CHECK FOR XON/XOFF AND SET lcr |= DMF_AUTOX; */
                    545:        }
                    546:        if (tp->t_flags&EVENP)
                    547:                lpar |= EPAR;
                    548:        if ((tp->t_ospeed) == B110)
                    549:                lpar |= TWOSB;
                    550:        lpar |= (unit&07);
                    551:        addr->dmflpr = lpar;
                    552:        addr->dmflctms = (addr->dmflctms &~ 0xff) | lcr;
                    553:        splx(s);
                    554: }
                    555: 
                    556: /*
                    557:  * DMF32 transmitter interrupt.
                    558:  * Restart the idle line.
                    559:  */
                    560: dmfxint(dmf)
                    561:        int dmf;
                    562: {
                    563:        int unit0 = dmf * 8;
                    564:        struct tty *tp0 = &dmf_tty[unit0];
                    565:        register struct tty *tp;
                    566:        register struct dmfdevice *addr;
                    567:        register struct uba_device *ui;
                    568:        register int t;
                    569:        short cntr;
                    570: 
                    571:        ui = dmfinfo[dmf];
                    572:        addr = (struct dmfdevice *)ui->ui_addr;
                    573:        while ((t = addr->dmfcsr) & DMF_TI) {
                    574:                if (t & DMF_NXM)
                    575:                        /* SHOULD RESTART OR SOMETHING... */
                    576:                        printf("dmf%d: NXM line %d\n", dmf, t >> 8 & 7);
                    577:                t = t >> 8 & 7;
                    578:                tp = tp0 + t;
                    579:                tp->t_state &= ~TS_BUSY;
                    580:                if (tp->t_state&TS_FLUSH)
                    581:                        tp->t_state &= ~TS_FLUSH;
                    582:                else if (dmf_dma[unit0 + t]) {
                    583:                        /*
                    584:                         * Do arithmetic in a short to make up
                    585:                         * for lost 16&17 bits.
                    586:                         */
                    587:                        addr->dmfcsr = DMFIR_TBA | DMF_IE | t;
                    588:                        cntr = addr->dmftba -
                    589:                            UBACVT(tp->t_outq.c_cf, ui->ui_ubanum);
                    590:                        ndflush(&tp->t_outq, (int)cntr);
                    591:                }
                    592:                if (tp->t_line)
                    593:                        (*linesw[tp->t_line].l_start)(tp);
                    594:                else
                    595:                        dmfstart(tp);
                    596:        }
                    597: }
                    598: 
                    599: /*
                    600:  * Start (restart) transmission on the given DMF32 line.
                    601:  */
                    602: dmfstart(tp)
                    603:        register struct tty *tp;
                    604: {
                    605:        register struct dmfdevice *addr;
                    606:        register int unit, nch;
                    607:        int s;
                    608:        register int dmf;
                    609: 
                    610:        unit = minor(tp->t_dev);
                    611:        dmf = unit >> 3;
                    612:        unit &= 07;
                    613:        addr = (struct dmfdevice *)tp->t_addr;
                    614: 
                    615:        /*
                    616:         * Must hold interrupts in following code to prevent
                    617:         * state of the tp from changing.
                    618:         */
                    619:        s = spltty();
                    620:        /*
                    621:         * If it's currently active, or delaying, no need to do anything.
                    622:         */
                    623:        if (tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
                    624:                goto out;
                    625:        /*
                    626:         * If there are still characters in the silo,
                    627:         * just reenable the transmitter.
                    628:         */
                    629:        addr->dmfcsr = DMF_IE | DMFIR_TBUF | unit;
                    630:        if (addr->dmftsc) {
                    631:                addr->dmfcsr = DMF_IE | DMFIR_LCR | unit;
                    632:                addr->dmflctms = addr->dmflctms | DMF_TE;
                    633:                tp->t_state |= TS_BUSY;
                    634:                goto out;
                    635:        }
                    636:        /*
                    637:         * If there are sleepers, and output has drained below low
                    638:         * water mark, wake up the sleepers.
                    639:         */
                    640:        if (tp->t_outq.c_cc<=TTLOWAT(tp)) {
                    641:                if (tp->t_state&TS_ASLEEP) {
                    642:                        tp->t_state &= ~TS_ASLEEP;
                    643:                        wakeup((caddr_t)&tp->t_outq);
                    644:                }
                    645:                if (tp->t_wsel) {
                    646:                        selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
                    647:                        tp->t_wsel = 0;
                    648:                        tp->t_state &= ~TS_WCOLL;
                    649:                }
                    650:        }
                    651:        /*
                    652:         * Now restart transmission unless the output queue is
                    653:         * empty.
                    654:         */
                    655:        if (tp->t_outq.c_cc == 0)
                    656:                goto out;
                    657:        if (tp->t_flags & (RAW|LITOUT))
                    658:                nch = ndqb(&tp->t_outq, 0);
                    659:        else {
                    660:                if ((nch = ndqb(&tp->t_outq, 0200)) == 0) {
                    661:                        /*
                    662:                        * If first thing on queue is a delay process it.
                    663:                        */
                    664:                        nch = getc(&tp->t_outq);
                    665:                        timeout(ttrstrt, (caddr_t)tp, (nch&0x7f)+6);
                    666:                        tp->t_state |= TS_TIMEOUT;
                    667:                        goto out;
                    668:                }
                    669:        }
                    670:        /*
                    671:         * If characters to transmit, restart transmission.
                    672:         */
                    673:        if (nch >= dmf_mindma) {
                    674:                register car;
                    675: 
                    676:                dmf_dma[minor(tp->t_dev)] = 1;
                    677:                addr->dmfcsr = DMF_IE | DMFIR_LCR | unit;
                    678:                addr->dmflctms = addr->dmflctms | DMF_TE;
                    679:                car = UBACVT(tp->t_outq.c_cf, dmfinfo[dmf]->ui_ubanum);
                    680:                addr->dmfcsr = DMF_IE | DMFIR_TBA | unit;
                    681:                addr->dmftba = car;
                    682:                addr->dmftcc = ((car >> 2) & 0xc000) | nch;
                    683:                tp->t_state |= TS_BUSY;
                    684:        } else if (nch) {
                    685:                register char *cp = tp->t_outq.c_cf;
                    686:                register int i;
                    687: 
                    688:                dmf_dma[minor(tp->t_dev)] = 0;
                    689:                nch = MIN(nch, DMF_SILOCNT);
                    690:                addr->dmfcsr = DMF_IE | DMFIR_LCR | unit;
                    691:                addr->dmflctms = addr->dmflctms | DMF_TE;
                    692:                addr->dmfcsr = DMF_IE | DMFIR_TBUF | unit;
                    693:                for (i = 0; i < nch; i++)
                    694:                        addr->dmftbuf = *cp++;
                    695:                ndflush(&tp->t_outq, nch);
                    696:                tp->t_state |= TS_BUSY;
                    697:        }
                    698: out:
                    699:        splx(s);
                    700: }
                    701: 
                    702: /*
                    703:  * Stop output on a line, e.g. for ^S/^Q or output flush.
                    704:  */
                    705: /*ARGSUSED*/
                    706: dmfstop(tp, flag)
                    707:        register struct tty *tp;
                    708: {
                    709:        register struct dmfdevice *addr;
                    710:        register unit = minor(tp->t_dev) & 7;
                    711:        int s;
                    712: 
                    713:        addr = (struct dmfdevice *)tp->t_addr;
                    714:        /*
                    715:         * Block input/output interrupts while messing with state.
                    716:         */
                    717:        s = spltty();
                    718:        if (flag) {
                    719:                addr->dmfcsr = DMF_IE | DMFIR_TBUF | unit;
                    720:                if (addr->dmftsc) {
                    721:                        /*
                    722:                         * Flush regardless of whether we're transmitting
                    723:                         * (TS_BUSY), if the silo contains untransmitted
                    724:                         * characters.
                    725:                         */
                    726:                        addr->dmfcsr = DMFIR_LCR | unit | DMF_IE;
                    727:                        addr->dmflctms = addr->dmflctms | DMF_TE | DMF_FLUSH;
                    728:                        /* this will interrupt so let dmfxint handle the rest */
                    729:                        tp->t_state |= TS_FLUSH|TS_BUSY;
                    730:                }
                    731:        } else {
                    732:                if (tp->t_state & TS_BUSY) {
                    733:                        /*
                    734:                         * Stop transmission by disabling
                    735:                         * the transmitter.  We'll pick up where we
                    736:                         * left off by reenabling in dmfstart.
                    737:                         */
                    738:                        addr->dmfcsr = DMFIR_LCR | unit | DMF_IE;
                    739:                        addr->dmflctms = addr->dmflctms &~ DMF_TE;
                    740:                        /* no interrupt here */
                    741:                        tp->t_state &= ~TS_BUSY;
                    742:                }
                    743:        }
                    744:        splx(s);
                    745: }
                    746: 
                    747: /*
                    748:  * DMF32 modem control
                    749:  */
                    750: dmfmctl(dev, bits, how)
                    751:        dev_t dev;
                    752:        int bits, how;
                    753: {
                    754:        register struct dmfdevice *dmfaddr;
                    755:        register int unit, mbits, lcr;
                    756:        int s;
                    757: 
                    758:        unit = minor(dev);
                    759:        dmfaddr = (struct dmfdevice *)(dmf_tty[unit].t_addr);
                    760:        unit &= 07;
                    761:        s = spltty();
                    762:        dmfaddr->dmfcsr = DMF_IE | DMFIR_TBUF | unit;
                    763:        mbits = dmfaddr->dmfrms << 8;
                    764:        dmfaddr->dmfcsr = DMF_IE | DMFIR_LCR | unit;
                    765:        lcr = dmfaddr->dmflctms;
                    766:        mbits |= (lcr & 0xff00) >> 8;
                    767:        switch (how) {
                    768:        case DMSET:
                    769:                mbits = (mbits &0xff00) | bits;
                    770:                break;
                    771: 
                    772:        case DMBIS:
                    773:                mbits |= bits;
                    774:                break;
                    775: 
                    776:        case DMBIC:
                    777:                mbits &= ~bits;
                    778:                break;
                    779: 
                    780:        case DMGET:
                    781:                (void) splx(s);
                    782:                return(mbits);
                    783:        }
                    784:        if (mbits & DMF_BRK)
                    785:                lcr |= DMF_RBRK;
                    786:        else
                    787:                lcr &= ~DMF_RBRK;
                    788:        dmfaddr->dmflctms = ((mbits & 037) << 8) | (lcr & 0xff);
                    789:        (void) splx(s);
                    790:        return(mbits);
                    791: }
                    792: 
                    793: /*
                    794:  * Reset state of driver if UBA reset was necessary.
                    795:  * Reset the csr, lpr, and lcr registers on open lines, and
                    796:  * restart transmitters.
                    797:  */
                    798: dmfreset(uban)
                    799:        int uban;
                    800: {
                    801:        register int dmf, unit;
                    802:        register struct tty *tp;
                    803:        register struct uba_device *ui;
                    804:        register struct dmfdevice *addr;
                    805:        int i;
                    806: 
                    807:        for (dmf = 0; dmf < NDMF; dmf++) {
                    808:                ui = dmfinfo[dmf];
                    809:                if (ui == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban)
                    810:                        continue;
                    811:                printf(" dmf%d", dmf);
                    812:                if (dmf_ubinfo[uban]) {
                    813:                        dmf_ubinfo[uban] = uballoc(uban, (caddr_t)cfree,
                    814:                            nclist*sizeof (struct cblock), 0);
                    815:                        cbase[uban] = UBAI_ADDR(dmf_ubinfo[uban]);
                    816:                }
                    817:                addr = (struct dmfdevice *)ui->ui_addr;
                    818:                addr->dmfcsr = DMF_IE;
                    819:                addr->dmfrsp = dmf_timeout;
                    820:                unit = dmf * 8;
                    821:                for (i = 0; i < 8; i++) {
                    822:                        tp = &dmf_tty[unit];
                    823:                        if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) {
                    824:                                dmfparam(unit);
                    825:                                (void) dmfmctl(unit, DMF_ON, DMSET);
                    826:                                tp->t_state &= ~TS_BUSY;
                    827:                                dmfstart(tp);
                    828:                        }
                    829:                        unit++;
                    830:                }
                    831:        }
                    832: }
                    833: 
                    834: /*
                    835:  * dmflopen -- open the line printer port on a dmf32
                    836:  */
                    837: /* ARGSUSED */
                    838: dmflopen(dev, flag)
                    839:        dev_t dev;
                    840:        int flag;
                    841: {
                    842:        register int dmf;
                    843:        register struct dmfl_softc *sc;
                    844:        register struct uba_device *ui;
                    845:        register struct dmfdevice *addr;
                    846: 
                    847:        dmf = DMFL_UNIT(dev);
                    848:        if (dmf >= NDMF || (ui = dmfinfo[dmf]) == 0 || ui->ui_alive == 0)
                    849:                return (ENXIO);
                    850:        sc = &dmfl_softc[dmf];
                    851:        if (sc->dmfl_state & OPEN)
                    852:                return (EBUSY);
                    853:        addr = (struct dmfdevice *)ui->ui_addr;
                    854:        if (addr->dmfl_ctrl & DMFL_OFFLINE) {
                    855: #ifdef notdef
                    856:                log(LOG_WARNING, "dmf%d: line printer offline/jammed\n",
                    857:                        dmf);
                    858: #endif
                    859:                return (EIO);
                    860:        }
                    861:        if ((addr->dmfl_ctrl & DMFL_CONV)) {
                    862:                log(LOG_WARNING, "dmf%d: line printer disconnected\n", dmf);
                    863:                return (EIO);
                    864:        }
                    865: 
                    866:        addr->dmfl_ctrl = 0;
                    867:        sc->dmfl_state |= OPEN;
                    868:        return (0);
                    869: }
                    870: 
                    871: /* ARGSUSED */
                    872: dmflclose(dev, flag)
                    873:        dev_t dev;
                    874:        int flag;
                    875: {
                    876:        register int dmf = DMFL_UNIT(dev);
                    877:        register struct dmfl_softc *sc = &dmfl_softc[dmf];
                    878:        register struct uba_device *ui = dmfinfo[dmf];
                    879: 
                    880:        sc->dmfl_state = 0;
                    881:        if (sc->dmfl_info != 0)
                    882:                ubarelse((int)ui->ui_ubanum, &sc->dmfl_info);
                    883: 
                    884:        ((struct dmfdevice *)ui->ui_addr)->dmfl_ctrl = 0;
                    885: }
                    886: 
                    887: dmflwrite(dev, uio)
                    888:        dev_t dev;
                    889:        struct uio *uio;
                    890: {
                    891:        register int n;
                    892:        register int error;
                    893:        register struct dmfl_softc *sc;
                    894: 
                    895:        sc = &dmfl_softc[DMFL_UNIT(dev)];
                    896:        if (sc->dmfl_state & ERROR)
                    897:                return (EIO);
                    898:        while (n = (unsigned)uio->uio_resid) {
                    899:                if (n > DMFL_BUFSIZ) {
                    900:                        n = DMFL_BUFSIZ;
                    901:                        sc->dmfl_state |= MOREIO;
                    902:                } else
                    903:                        sc->dmfl_state &= ~MOREIO;
                    904:                if (error = uiomove(sc->dmfl_buf, (int)n, UIO_WRITE, uio))
                    905:                        return (error);
                    906:                if (error = dmflout(dev, sc->dmfl_buf, n))
                    907:                        return (error);
                    908:        }
                    909:        return (0);
                    910: }
                    911: 
                    912: 
                    913: /*
                    914:  * dmflout -- start io operation to dmf line printer
                    915:  *             cp is addr of buf of n chars to be sent.
                    916:  *
                    917:  *     -- dmf will be put in formatted output mode, this will
                    918:  *             be selectable from an ioctl if the
                    919:  *             need ever arises.
                    920:  */
                    921: dmflout(dev, cp, n)
                    922:        dev_t dev;
                    923:        char *cp;
                    924:        int n;
                    925: {
                    926:        register struct dmfl_softc *sc;
                    927:        register int dmf;
                    928:        register struct uba_device *ui;
                    929:        register struct dmfdevice *d;
                    930:        int s;
                    931: 
                    932:        dmf = DMFL_UNIT(dev);
                    933:        sc = &dmfl_softc[dmf];
                    934:        if (sc->dmfl_state & ERROR)
                    935:                return (EIO);
                    936:        ui = dmfinfo[dmf];
                    937:        /*
                    938:         * allocate unibus resources, will be released when io
                    939:         * operation is done.
                    940:         */
                    941:        if (sc->dmfl_info == 0)
                    942:                sc->dmfl_info = uballoc(ui->ui_ubanum, cp, n, 0);
                    943:        d = (struct dmfdevice *)ui->ui_addr;
                    944:        d->dmfl_ctrl = sc->dmfl_format;         /* indir reg 2 */
                    945:        /* indir reg auto increments on r/w */
                    946:        /* SO DON'T CHANGE THE ORDER OF THIS CODE */
                    947:        d->dmfl_indrct = 0;                     /* prefix chars & num */
                    948:        d->dmfl_indrct = 0;                     /* suffix chars & num */
                    949:        d->dmfl_indrct = sc->dmfl_info;         /* dma lo 16 bits addr */
                    950:        d->dmfl_indrct = -n;                    /* number of chars */
                    951: 
                    952:        d->dmfl_indrct = ((sc->dmfl_info>>16)&3) | DMFL_OPTIONS;
                    953:                                                /* dma hi 2 bits addr */
                    954:        d->dmfl_indrct = sc->dmfl_lines         /* lines per page */
                    955:                | (sc->dmfl_cols<<8);           /* carriage width */
                    956:        sc->dmfl_state |= ASLP;
                    957:        s = spltty();
                    958:        d->dmfl_ctrl |= DMFL_PEN | DMFL_IE;
                    959:        while (sc->dmfl_state & ASLP) {
                    960:                sleep(sc->dmfl_buf, PZERO + 8);
                    961:                while (sc->dmfl_state & ERROR) {
                    962:                        timeout(dmflint, (caddr_t)dmf, 10 * hz);
                    963:                        sleep((caddr_t)&sc->dmfl_state, PZERO + 8);
                    964:                }
                    965:        }
                    966:        splx(s);
                    967:        return (0);
                    968: }
                    969: 
                    970: /*
                    971:  * dmflint -- handle an interrupt from the line printer part of the dmf32
                    972:  */
                    973: dmflint(dmf)
                    974:        int dmf;
                    975: {
                    976:        register struct uba_device *ui;
                    977:        register struct dmfl_softc *sc;
                    978:        register struct dmfdevice *d;
                    979:        short dmfl_stats;
                    980: 
                    981:        ui = dmfinfo[dmf];
                    982:        sc = &dmfl_softc[dmf];
                    983:        d = (struct dmfdevice *)ui->ui_addr;
                    984: 
                    985:        d->dmfl_ctrl &= ~DMFL_IE;
                    986:        dmfl_stats = d->dmfl_ctrl;
                    987:        if (sc->dmfl_state & ERROR) {
                    988:                if ((dmfl_stats & DMFL_OFFLINE) == 0)
                    989:                        sc->dmfl_state &= ~ERROR;
                    990:                wakeup((caddr_t)&sc->dmfl_state);
                    991:                return;
                    992:        }
                    993:        if (dmfl_stats & DMFL_DMAERR)
                    994:                log(LOG_WARNING, "dmf%d: NXM\n", dmf);
                    995:        if (dmfl_stats & DMFL_OFFLINE) {
                    996:                log(LOG_WARNING, "dmf%d: printer error\n", dmf);
                    997:                sc->dmfl_state |= ERROR;
                    998:        }
                    999: #ifdef notdef
                   1000:        if (dmfl_stats & DMFL_PDONE) {
                   1001:                printf("bytes= %d\n", d->dmfl_indrct);
                   1002:                printf("lines= %d\n", d->dmfl_indrct);
                   1003:        }
                   1004: #endif
                   1005:        sc->dmfl_state &= ~ASLP;
                   1006:        wakeup((caddr_t)sc->dmfl_buf);
                   1007:        if (sc->dmfl_info && (sc->dmfl_state & MOREIO) == 0)
                   1008:                ubarelse(ui->ui_ubanum, &sc->dmfl_info);
                   1009: }
                   1010: 
                   1011: /* stubs for interrupt routines for devices not yet supported */
                   1012: 
                   1013: dmfsrint()
                   1014: {
                   1015:        printf("dmfsrint\n");
                   1016: }
                   1017: 
                   1018: dmfsxint()
                   1019: {
                   1020:        printf("dmfsxint\n");
                   1021: }
                   1022: 
                   1023: dmfdaint()
                   1024: {
                   1025:        printf("dmfdaint\n");
                   1026: }
                   1027: 
                   1028: dmfdbint()
                   1029: {
                   1030:        printf("dmfdbint\n");
                   1031: }
                   1032: #endif NDMF

unix.superglobalmegacorp.com

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