Annotation of 43BSDReno/sys/tahoevba/dr.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1988 The Regents of the University of California.
        !             3:  * All rights reserved.
        !             4:  *
        !             5:  * This code is derived from software contributed to Berkeley by
        !             6:  * Computer Consoles Inc.
        !             7:  *
        !             8:  * Redistribution is only permitted until one year after the first shipment
        !             9:  * of 4.4BSD by the Regents.  Otherwise, redistribution and use in source and
        !            10:  * binary forms are permitted provided that: (1) source distributions retain
        !            11:  * this entire copyright notice and comment, and (2) distributions including
        !            12:  * binaries display the following acknowledgement:  This product includes
        !            13:  * software developed by the University of California, Berkeley and its
        !            14:  * contributors'' in the documentation or other materials provided with the
        !            15:  * distribution and in all advertising materials mentioning features or use
        !            16:  * of this software.  Neither the name of the University nor the names of
        !            17:  * its contributors may be used to endorse or promote products derived from
        !            18:  * this software without specific prior written permission.
        !            19:  * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
        !            20:  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
        !            21:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
        !            22:  *
        !            23:  *     @(#)dr.c        7.8 (Berkeley) 6/28/90
        !            24:  */
        !            25: 
        !            26: #include "dr.h"
        !            27: #if NDR > 0
        !            28: /*
        !            29:  * DRV11-W DMA interface driver.
        !            30:  *
        !            31:  * UNTESTED WITH 4.3
        !            32:  */
        !            33: #include "machine/mtpr.h"
        !            34: #include "machine/pte.h"
        !            35: 
        !            36: #include "param.h"
        !            37: #include "conf.h"
        !            38: #include "user.h"
        !            39: #include "proc.h"
        !            40: #include "map.h"
        !            41: #include "ioctl.h"
        !            42: #include "buf.h"
        !            43: #include "vm.h"
        !            44: #include "kernel.h"
        !            45: 
        !            46: #include "../tahoevba/vbavar.h"
        !            47: #include "../tahoevba/drreg.h"
        !            48: 
        !            49: #define YES 1
        !            50: #define NO  0
        !            51: 
        !            52: struct  vba_device  *drinfo[NDR];
        !            53: struct  dr_aux dr_aux[NDR];
        !            54: 
        !            55: unsigned drminphys();
        !            56: int     drprobe(), drintr(), drattach(), drtimo(), drrwtimo();
        !            57: int     drstrategy();
        !            58: extern struct  vba_device  *drinfo[];
        !            59: static long drstd[] = { 0 };
        !            60: struct  vba_driver drdriver =
        !            61:     { drprobe, 0, drattach, 0, drstd, "rs", drinfo };
        !            62: 
        !            63: #define RSUNIT(dev) (minor(dev) & 7)
        !            64: #define SPL_UP spl5
        !            65: 
        !            66: /* -------- Per-unit data -------- */
        !            67: 
        !            68: extern struct dr_aux dr_aux[];
        !            69: 
        !            70: #ifdef DR_DEBUG
        !            71: long   DR11 = 0;
        !            72: #endif
        !            73: 
        !            74: drprobe(reg, vi)
        !            75:        caddr_t reg;
        !            76:        struct vba_device *vi;
        !            77: {
        !            78:        register int br, cvec;          /* must be r12, r11 */
        !            79:        struct rsdevice *dr;
        !            80: 
        !            81: #ifdef lint
        !            82:        br = 0; cvec = br; br = cvec;
        !            83:        drintr(0);
        !            84: #endif
        !            85:        if (badaddr(reg, 2))
        !            86:                return (0);
        !            87:        dr = (struct rsdevice *)reg;
        !            88:        dr->dr_intvect = --vi->ui_hd->vh_lastiv;
        !            89: #ifdef DR_DEBUG
        !            90:        printf("dprobe: Set interrupt vector %lx and init\n",dr->dr_intvec);
        !            91: #endif
        !            92:        /* generate interrupt here for autoconfig */
        !            93:        dr->dr_cstat = MCLR;            /* init board and device */
        !            94: #ifdef DR_DEBUG
        !            95:        printf("drprobe: Initial status %lx\n", dr->dr_cstat);
        !            96: #endif
        !            97:        br = 0x18, cvec = dr->dr_intvect;       /* XXX */
        !            98:        return (sizeof (struct rsdevice));              /* DR11 exist */
        !            99: }
        !           100: 
        !           101: /* ARGSUSED */
        !           102: drattach(ui)
        !           103:        struct vba_device *ui;
        !           104: {
        !           105:        register struct dr_aux *rsd;
        !           106: 
        !           107:        rsd = &dr_aux[ui->ui_unit];
        !           108:        rsd->dr_flags = DR_PRES;                /* This dr11 is present */
        !           109:        rsd->dr_addr = (struct rsdevice *)ui->ui_addr; /* Save addr of this dr11 */
        !           110:        rsd->dr_istat = 0;
        !           111:        rsd->dr_bycnt = 0;
        !           112:        rsd->dr_cmd = 0;
        !           113:        rsd->currenttimo = 0;
        !           114: }
        !           115: 
        !           116: /*ARGSUSED*/
        !           117: dropen(dev, flag)
        !           118:        dev_t dev;
        !           119:        int flag;
        !           120: {
        !           121:        register int unit = RSUNIT(dev);
        !           122:        register struct rsdevice *dr;
        !           123:        register struct dr_aux *rsd;
        !           124: 
        !           125:        if (drinfo[unit] == 0 || !drinfo[unit]->ui_alive)
        !           126:                return (ENXIO);
        !           127:        dr = RSADDR(unit);
        !           128:        rsd = &dr_aux[unit];
        !           129:        if (rsd->dr_flags & DR_OPEN) {
        !           130: #ifdef DR_DEBUG
        !           131:                printf("\ndropen: dr11 unit %ld already open",unit);
        !           132: #endif
        !           133:                return (ENXIO);                 /* DR11 already open */
        !           134:        }
        !           135:        rsd->dr_flags |= DR_OPEN;       /* Mark it OPEN */
        !           136:        rsd->dr_istat = 0;              /* Clear status of previous interrupt */
        !           137:        rsd->rtimoticks = hz;           /* Set read no stall timout to 1 sec */
        !           138:        rsd->wtimoticks = hz*60;        /* Set write no stall timout to 1 min */
        !           139:        dr->dr_cstat = DR_ZERO;         /* Clear function & latches */
        !           140:        dr->dr_pulse = (RDMA | RATN);   /* clear leftover attn & e-o-r flags */
        !           141:        drtimo(dev);                    /* start the self kicker */
        !           142:        return (0);
        !           143: }
        !           144: 
        !           145: drclose (dev)
        !           146:        dev_t dev;
        !           147: {
        !           148:        register int unit = RSUNIT(dev);
        !           149:        register struct dr_aux *dra;
        !           150:        register struct rsdevice *rs;
        !           151:        register short s;
        !           152: 
        !           153:        dra = &dr_aux[unit];
        !           154:        if ((dra->dr_flags & DR_OPEN) == 0) {
        !           155: #ifdef DR_DEBUG
        !           156:                printf("\ndrclose: DR11 device %ld not open",unit);
        !           157: #endif
        !           158:                return;
        !           159:        }
        !           160:        dra->dr_flags &= ~(DR_OPEN|DR_ACTV);
        !           161:        rs = dra->dr_addr;
        !           162:        s = SPL_UP();
        !           163:        rs->dr_cstat = DR_ZERO;
        !           164:        if (dra->dr_buf.b_flags & B_BUSY) {
        !           165:                dra->dr_buf.b_flags &= ~B_BUSY;
        !           166:                wakeup((caddr_t)&dra->dr_buf.b_flags);
        !           167:        }
        !           168:        splx(s);
        !           169:        return (0);
        !           170: }
        !           171: 
        !           172: 
        !           173: /*     drread() works exactly like drwrite() except that the
        !           174:        B_READ flag is used when physio() is called
        !           175: */
        !           176: drread (dev, uio)
        !           177:        dev_t dev;
        !           178:        struct uio *uio;
        !           179: {      register struct dr_aux *dra;
        !           180:        register struct buf *bp;
        !           181:        register int spl, err;
        !           182:        register int unit = RSUNIT(dev);
        !           183: 
        !           184:        if (uio->uio_iov->iov_len <= 0 ||       /* Negative count */
        !           185:            uio->uio_iov->iov_len & 1 ||        /* odd count */
        !           186:            (int)uio->uio_iov->iov_base & 1)    /* odd destination address */
        !           187:                return (EINVAL);
        !           188: #ifdef DR_DEBUG
        !           189:        if (DR11 & 8)
        !           190:                printf("\ndrread: (len:%ld)(base:%lx)",
        !           191:                    uio->uio_iov->iov_len,(int)uio->uio_iov->iov_base); 
        !           192: #endif
        !           193:        dra = &dr_aux[RSUNIT(dev)];
        !           194:        dra->dr_op = DR_READ;
        !           195:        bp =  &dra->dr_buf;
        !           196:        bp->b_resid = 0;
        !           197:        if (dra->dr_flags & DR_NORSTALL) {
        !           198:                /*
        !           199:                 * We are in no stall mode, start the timer,
        !           200:                 * raise IPL so nothing can stop us once the
        !           201:                 * timer's running
        !           202:                 */
        !           203:                spl = SPL_UP();
        !           204:                timeout(drrwtimo, (caddr_t)((dra->currenttimo<<8) | unit),
        !           205:                    (int)dra->rtimoticks);
        !           206:                err = physio(drstrategy, bp, dev,B_READ, drminphys, uio);
        !           207:                splx(spl);
        !           208:                if (err)
        !           209:                        return (err);
        !           210:                dra->currenttimo++;     /* Update current timeout number */
        !           211:                /* Did we timeout */
        !           212:                if (dra->dr_flags & DR_TMDM)
        !           213:                        dra->dr_flags &= ~DR_TMDM; /* Clear timeout flag */
        !           214:                return (err);
        !           215:        }
        !           216:        return (physio(drstrategy, bp, dev,B_READ, drminphys, uio));
        !           217: }
        !           218: 
        !           219: drwrite(dev, uio)
        !           220:        dev_t dev;
        !           221:        struct uio *uio;
        !           222: {      register struct dr_aux *dra;
        !           223:        register struct buf *bp;
        !           224:        register int unit = RSUNIT(dev);
        !           225:        int spl, err;
        !           226: 
        !           227:        if (uio->uio_iov->iov_len <= 0 || uio->uio_iov->iov_len & 1 ||
        !           228:            (int)uio->uio_iov->iov_base & 1)
        !           229:                return (EINVAL);
        !           230: #ifdef DR_DEBUG
        !           231:        if (DR11 & 4)
        !           232:                printf("\ndrwrite: (len:%ld)(base:%lx)",
        !           233:                    uio->uio_iov->iov_len,(int)uio->uio_iov->iov_base); 
        !           234: #endif
        !           235:        dra = &dr_aux[RSUNIT(dev)];
        !           236:        dra->dr_op = DR_WRITE;
        !           237:        bp =  &dra->dr_buf;
        !           238:        bp->b_resid = 0;
        !           239:        if (dra->dr_flags & DR_NOWSTALL) {
        !           240:                /*
        !           241:                 * We are in no stall mode, start the timer,
        !           242:                 * raise IPL so nothing can stop us once the
        !           243:                 * timer's running
        !           244:                 */
        !           245:                spl = SPL_UP();
        !           246:                timeout(drrwtimo,(caddr_t)((dra->currenttimo<<8) | unit),
        !           247:                    (int)dra->wtimoticks);
        !           248:                err = physio (drstrategy, bp, dev,B_WRITE, drminphys, uio);
        !           249:                splx(spl);
        !           250:                if (err)
        !           251:                        return (err);
        !           252:                dra->currenttimo++;     /* Update current timeout number */
        !           253:                /* Did we timeout */
        !           254:                if (dra->dr_flags & DR_TMDM)
        !           255:                        dra->dr_flags &= ~DR_TMDM;      /* Clear timeout flag */
        !           256:                return (err);
        !           257:        }
        !           258:        return (physio(drstrategy, bp, dev,B_WRITE, drminphys, uio));
        !           259: }
        !           260: 
        !           261: /*
        !           262:  * Routine used by calling program to issue commands to dr11 driver and 
        !           263:  * through it to the device.
        !           264:  * It is also used to read status from the device and driver and to wait 
        !           265:  * for attention interrupts.
        !           266:  * Status is returned in an 8 elements unsigned short integer array, the 
        !           267:  * first two elements of the array are also used to pass arguments to 
        !           268:  * drioctl() if required.
        !           269:  * The function bits to be written to the dr11 are included in the cmd
        !           270:  * argument. Even if they are not being written to the dr11 in a particular
        !           271:  * drioctl() call, they will update the copy of cmd that is stored in the
        !           272:  * driver. When drstrategy() is called, this updated copy is used if a 
        !           273:  * deferred function bit write has been specified. The "side effect" of
        !           274:  * calls to the drioctl() requires that the last call prior to a read or
        !           275:  * write has an appropriate copy of the function bits in cmd if they are
        !           276:  * to be used in drstrategy().
        !           277:  * When used as command value, the contents of data[0] is the command
        !           278:  * parameter.
        !           279:  */
        !           280: drioctl(dev, cmd, data)
        !           281:        dev_t dev;
        !           282:        int cmd;
        !           283:        long *data;
        !           284: {
        !           285:        register int unit = RSUNIT(dev);
        !           286:        register struct dr_aux *dra;
        !           287:        register struct rsdevice *rsaddr = RSADDR(unit);
        !           288:        int s, error = 0;
        !           289:        u_short status;
        !           290:        long temp;
        !           291: 
        !           292: #ifdef DR_DEBUG
        !           293:        if (DR11 & 0x10)
        !           294:                printf("\ndrioctl: (dev:%lx)(cmd:%lx)(data:%lx)(data[0]:%lx)",
        !           295:                    dev,cmd,data,data[0]);
        !           296: #endif
        !           297:        dra = &dr_aux[unit];
        !           298:        dra->dr_cmd = 0;        /* Fresh copy; clear all previous flags */
        !           299:        switch (cmd) {
        !           300: 
        !           301:        case DRWAIT:            /* Wait for attention interrupt */
        !           302: #ifdef DR_DEBUG
        !           303:                printf("\ndrioctl: wait for attention interrupt");
        !           304: #endif
        !           305:                s = SPL_UP();
        !           306:                /* 
        !           307:                 * If the attention flag in dr_flags is set, it probably
        !           308:                 * means that an attention has arrived by the time a
        !           309:                 * previous DMA end-of-range interrupt was serviced. If
        !           310:                 * ATRX is set, we will return with out sleeping, since
        !           311:                 * we have received an attention since the last call to
        !           312:                 * wait on attention.  This may not be appropriate for
        !           313:                 * some applications.
        !           314:                 */
        !           315:                if ((dra->dr_flags & DR_ATRX) == 0) {
        !           316:                        dra->dr_flags |= DR_ATWT;       /* Set waiting flag */
        !           317:                        /*
        !           318:                         * Enable interrupt; use pulse reg.
        !           319:                         * so function bits are not changed
        !           320:                         */
        !           321:                        rsaddr->dr_pulse = IENB;
        !           322:                        error = tsleep((caddr_t)&dra->dr_cmd, DRPRI | PCATCH,
        !           323:                            devio, 0);
        !           324:                }
        !           325:                splx(s);
        !           326:                break;
        !           327: 
        !           328:        case DRPIOW:                    /* Write to p-i/o register */
        !           329:                rsaddr->dr_data = data[0];
        !           330:                break;
        !           331: 
        !           332:        case DRPACL:                    /* Send pulse to device */
        !           333:                rsaddr->dr_pulse = FCN2;
        !           334:                break;
        !           335: 
        !           336:        case DRDACL:                    /* Defer alco pulse until go */
        !           337:                dra->dr_cmd |= DR_DACL;
        !           338:                break;
        !           339: 
        !           340:        case DRPCYL:                    /* Set cycle with next go */
        !           341:                dra->dr_cmd |= DR_PCYL;
        !           342:                break;
        !           343: 
        !           344:        case DRDFCN:                    /* Update function with next go */
        !           345:                dra->dr_cmd |= DR_DFCN;
        !           346:                break;
        !           347: 
        !           348:        case DRRATN:                    /* Reset attention flag */
        !           349:                rsaddr->dr_pulse = RATN;
        !           350:                break;
        !           351: 
        !           352:        case DRRDMA:                    /* Reset DMA e-o-r flag */
        !           353:                rsaddr->dr_pulse = RDMA;
        !           354:                break;
        !           355: 
        !           356:        case DRSFCN:                    /* Set function bits */
        !           357:                temp = data[0] & DR_FMSK;
        !           358:                /*
        !           359:                 * This has a very important side effect -- It clears
        !           360:                 * the interrupt enable flag. That is fine for this driver,
        !           361:                 * but if it is desired to leave interrupt enable at all
        !           362:                 * times, it will be necessary to read the status register
        !           363:                 * first to get IENB, or carry a software flag that indicates
        !           364:                 * whether interrupts are set, and or this into the control
        !           365:                 * register value being written.
        !           366:                 */
        !           367:                rsaddr->dr_cstat = temp;
        !           368:                break;
        !           369: 
        !           370:        case DRRPER:                    /* Clear parity flag */
        !           371:                rsaddr->dr_pulse = RPER;
        !           372:                break;
        !           373: 
        !           374:        case DRSETRSTALL:               /* Set read stall mode. */
        !           375:                dra->dr_flags &= (~DR_NORSTALL);
        !           376:                break;
        !           377: 
        !           378:        case DRSETNORSTALL:             /* Set no stall read  mode. */
        !           379:                dra->dr_flags |= DR_NORSTALL;
        !           380:                break;
        !           381: 
        !           382:        case DRGETRSTALL:               /* Returns true if in read stall mode */
        !           383:                data[0]  = (dra->dr_flags & DR_NORSTALL)? 0 : 1;
        !           384:                break;
        !           385: 
        !           386:        case DRSETRTIMEOUT:             /* Set read stall timeout (1/10 secs) */
        !           387:                if (data[0] < 1)
        !           388:                        error = EINVAL;
        !           389:                dra->rtimoticks = (data[0] * hz )/10;
        !           390:                break;
        !           391: 
        !           392:        case DRGETRTIMEOUT:             /* Return read stall timeout */
        !           393:                data[0] = ((dra->rtimoticks)*10)/hz;
        !           394:                break;
        !           395: 
        !           396:        case DRSETWSTALL:               /* Set write stall mode. */
        !           397:                dra->dr_flags &= (~DR_NOWSTALL);
        !           398:                break;
        !           399: 
        !           400:        case DRSETNOWSTALL:             /* Set write stall mode. */
        !           401:                dra->dr_flags |= DR_NOWSTALL;
        !           402:                break;
        !           403: 
        !           404:        case DRGETWSTALL:               /* Return true if in write stall mode */
        !           405:                data[0] = (dra->dr_flags & DR_NOWSTALL)? 0 : 1;
        !           406:                break;
        !           407: 
        !           408:        case DRSETWTIMEOUT:             /* Set write stall timeout (1/10's) */
        !           409:                if (data[0] < 1)
        !           410:                        error = EINVAL;
        !           411:                dra->wtimoticks = (data[0] * hz )/10;
        !           412:                break;
        !           413: 
        !           414:        case DRGETWTIMEOUT:             /* Return write stall timeout */
        !           415:                data[0] = ((dra->wtimoticks)*10)/hz;
        !           416:                break;
        !           417: 
        !           418:        case DRWRITEREADY:              /* Return true if can write data */
        !           419:                data[0] = (rsaddr->dr_cstat & STTA)? 1 : 0;
        !           420:                break;
        !           421: 
        !           422:        case DRREADREADY:               /* Return true if data to be read */
        !           423:                data[0] = (rsaddr->dr_cstat & STTB)? 1 : 0;
        !           424:                break;
        !           425: 
        !           426:        case DRBUSY:                    /* Return true if device busy */
        !           427:                /*
        !           428:                 * Internally this is the DR11-W
        !           429:                 * STAT C bit, but there is a bug in the Omega 500/FIFO
        !           430:                 * interface board that it cannot drive this signal low
        !           431:                 * for certain DR11-W ctlr such as the Ikon. We use the
        !           432:                 * REDY signal of the CSR on the Ikon DR11-W instead. 
        !           433:                 */
        !           434: #ifdef notdef
        !           435:                data[0] = (rsaddr->dr_cstat & STTC)? 1 : 0;
        !           436: #else
        !           437:                data[0] = ((rsaddr->dr_cstat & REDY)? 0 : 1);
        !           438: #endif
        !           439:                break;
        !           440: 
        !           441:        case DRRESET:                   /* Reset device */
        !           442:                /* Reset DMA ATN RPER flag */
        !           443:                rsaddr->dr_pulse = (MCLR|RDMA|RATN|RPER);
        !           444:                DELAY(0x1f000);
        !           445:                while ((rsaddr->dr_cstat & REDY) == 0 && error == 0)
        !           446:                        /* Wakeup by drtimo() */
        !           447:                        error = tsleep((caddr_t)dra, DRPRI | PCATCH, devio, 0); 
        !           448:                dra->dr_istat = 0;
        !           449:                dra->dr_cmd = 0;
        !           450:                dra->currenttimo = 0;
        !           451:                break;
        !           452: 
        !           453:        case DR11STAT: {                /* Copy back dr11 status to user */
        !           454:                register struct dr11io *dr = (struct dr11io *)data;
        !           455:                dr->arg[0] = dra->dr_flags;
        !           456:                dr->arg[1] = rsaddr->dr_cstat;
        !           457:                dr->arg[2] = dra->dr_istat;     /* Status at last interrupt */
        !           458:                dr->arg[3] = rsaddr->dr_data;   /* P-i/o input data */
        !           459:                status = (u_short)((rsaddr->dr_addmod << 8) & 0xff00);
        !           460:                dr->arg[4] = status | (u_short)(rsaddr->dr_intvect & 0xff);
        !           461:                dr->arg[5] = rsaddr->dr_range;
        !           462:                dr->arg[6] = rsaddr->dr_rahi;
        !           463:                dr->arg[7] = rsaddr->dr_ralo;
        !           464:                break;
        !           465:        }
        !           466:        case DR11LOOP:                  /* Perform loopback test */
        !           467:                /*
        !           468:                 * NB: MUST HAVE LOOPBACK CABLE ATTACHED --
        !           469:                 * Test results are printed on system console
        !           470:                 */
        !           471:                if (error = suser(u.u_cred, &u.u_acflag))
        !           472:                        break;
        !           473:                dr11loop(rsaddr, dra, unit);
        !           474:                break;
        !           475: 
        !           476:        default:
        !           477:                return (EINVAL);
        !           478:        }
        !           479: #ifdef DR_DEBUG
        !           480:        if (DR11 & 0x10)
        !           481:                printf("**** (data[0]:%lx)",data[0]);
        !           482: #endif
        !           483:        return (error);
        !           484: }
        !           485: 
        !           486: #define NPAT   2
        !           487: #define DMATBL 20
        !           488: u_short        tstpat[DMATBL] = { 0xAAAA, 0x5555};
        !           489: long   DMAin = 0;
        !           490: 
        !           491: /*
        !           492:  * Perform loopback test -- MUST HAVE LOOPBACK CABLE ATTACHED
        !           493:  * Test results are printed on system console
        !           494:  */
        !           495: dr11loop(dr, dra, unit)
        !           496:        struct rsdevice *dr;
        !           497:        struct dr_aux *dra;
        !           498:        int unit;
        !           499: {
        !           500:        register long result, ix;
        !           501:        long addr, wait;
        !           502: 
        !           503:        dr->dr_cstat = MCLR;            /* Clear board & device, disable intr */
        !           504:        printf("\n\t ----- DR11 unit %ld loopback test -----", unit);
        !           505:        printf("\n\t Program I/O ...");
        !           506:        for (ix=0;ix<NPAT;ix++) {
        !           507:                dr->dr_data = tstpat[ix];       /* Write to Data out register */
        !           508:                result = dr->dr_data & 0xFFFF;  /* Read it back */
        !           509:                if (result != tstpat[ix]) {
        !           510:                        printf("Failed, expected : %lx --- actual : %lx",
        !           511:                                tstpat[ix], result);
        !           512:                        return;
        !           513:                }
        !           514:        }
        !           515:        printf("OK\n\t Functions & Status Bits ...");
        !           516:        dr->dr_cstat = (FCN1 | FCN3);
        !           517:        result = dr->dr_cstat & 0xffff;         /* Read them back */
        !           518:        if ((result & (STTC | STTA)) != (STTC |STTA)) {
        !           519:                printf("Failed, expected : %lx --- actual : %lx, ISR:%lx",
        !           520:                        (STTA|STTC), (result & (STTA|STTC)), result);
        !           521:                return;
        !           522:        }
        !           523:        dr->dr_cstat = FCN2;
        !           524:        result = dr->dr_cstat & 0xffff;         /* Read them back */
        !           525:        if ((result & STTB) != STTB) {
        !           526:                printf("Failed, expected : %lx --- actual : %lx, ISR:%lx",
        !           527:                        STTB, (result & STTB), result);
        !           528:                return;
        !           529:        }
        !           530:        printf("OK\n\t DMA output ...");
        !           531:        if (DMAin)
        !           532:                goto dmain;
        !           533:        /* Initialize DMA data buffer */
        !           534:        for (ix=0; ix<DMATBL; ix++)
        !           535:                tstpat[ix] = 0xCCCC + ix;
        !           536:        tstpat[DMATBL-1] = 0xCCCC;      /* Last word output */
        !           537:        /* Setup normal DMA */
        !           538:        addr = (long)vtoph((struct proc *)0, (unsigned)tstpat);
        !           539:        dr->dr_walo = (addr >> 1) & 0xffff;
        !           540:        dr->dr_wahi = (addr >> 17) & 0x7fff;
        !           541:        /* Set DMA range count: (number of words - 1) */
        !           542:        dr->dr_range = DMATBL - 1;
        !           543:        /* Set address modifier code to be used for DMA access to memory */
        !           544:        dr->dr_addmod = DRADDMOD;
        !           545: 
        !           546:        /*
        !           547:         * Clear dmaf and attf to assure a clean dma start, also disable
        !           548:         * attention interrupt
        !           549:         */
        !           550:        dr->dr_pulse = RDMA|RATN|RMSK;  /* Use pulse register */
        !           551:        dr->dr_cstat = GO|CYCL;           /* GO...... */
        !           552: 
        !           553:        /* Wait for DMA complete; REDY and DMAF are true in ISR */
        !           554:        wait = 0;
        !           555:        while ((result=(dr->dr_cstat & (REDY|DMAF))) != (REDY|DMAF)) {
        !           556:                printf("\n\tWait for DMA complete...ISR : %lx", result);
        !           557:                if (++wait > 5) {
        !           558:                        printf("\n\t DMA output fails...timeout!!, ISR:%lx",
        !           559:                                result);
        !           560:                        return;
        !           561:                }
        !           562:        }
        !           563:        result = dr->dr_data & 0xffff;          /* Read last word output */     
        !           564:        if (result != 0xCCCC) {
        !           565:                printf("\n\t Fails, expected : %lx --- actual : %lx",
        !           566:                        0xCCCC, result);
        !           567:                return;
        !           568:        }
        !           569:        printf("OK\n\t DMA input ...");
        !           570: dmain:
        !           571:        dr->dr_data = 0x1111;           /* DMA input data */
        !           572:        /* Setup normal DMA */
        !           573:        addr = (long)vtoph((struct proc *)0, (unsigned)tstpat);
        !           574:        dr->dr_walo = (addr >> 1) & 0xffff;
        !           575:        dr->dr_wahi = (addr >> 17) & 0x7fff;
        !           576:        dr->dr_range = DMATBL - 1;
        !           577:        dr->dr_addmod = (char)DRADDMOD;
        !           578:        dr->dr_cstat = FCN1;            /* Set FCN1 in ICR to DMA in*/
        !           579:        if ((dra->dr_flags & DR_LOOPTST) == 0) {
        !           580:                /* Use pulse reg */  
        !           581:                dr->dr_pulse = RDMA|RATN|RMSK|CYCL|GO;
        !           582:                /* Wait for DMA complete; REDY and DMAF are true in ISR */
        !           583:                wait = 0;
        !           584:                while ((result=(dr->dr_cstat & (REDY|DMAF))) != (REDY|DMAF)) {
        !           585:                        printf("\n\tWait for DMA to complete...ISR:%lx",result);
        !           586:                        if (++wait > 5) {
        !           587:                                printf("\n\t DMA input timeout!!, ISR:%lx",
        !           588:                                        result);
        !           589:                                return;
        !           590:                        }
        !           591:                }
        !           592:        } else  {
        !           593:                /* Enable DMA e-o-r interrupt */
        !           594:                dr->dr_pulse = IENB|RDMA|RATN|CYCL|GO;
        !           595:                /* Wait for DMA complete; DR_LOOPTST is false in dra->dr_flags*/
        !           596:                wait = 0;
        !           597:                while (dra->dr_flags & DR_LOOPTST) { 
        !           598:                        result = dr->dr_cstat & 0xffff;
        !           599:                        printf("\n\tWait for DMA e-o-r intr...ISR:%lx", result);
        !           600:                        if (++wait > 7) {
        !           601:                                printf("\n\t DMA e-o-r timeout!!, ISR:%lx",
        !           602:                                        result);
        !           603:                                dra->dr_flags &= ~DR_LOOPTST;
        !           604:                                return;
        !           605:                        }
        !           606:                }
        !           607:                dra->dr_flags |= DR_LOOPTST;
        !           608:        }
        !           609:        mtpr(P1DC, tstpat);                     /* Purge cache */
        !           610:        mtpr(P1DC, 0x3ff+tstpat);
        !           611:        for (ix=0; ix<DMATBL; ix++) {
        !           612:                if (tstpat[ix] != 0x1111) {
        !           613:                        printf("\n\t Fails, ix:%d, expected:%x --- actual:%x",
        !           614:                                ix, 0x1111, tstpat[ix]);
        !           615:                        return;
        !           616:                }
        !           617:        }
        !           618:        if ((dra->dr_flags & DR_LOOPTST) == 0) {
        !           619:                dra->dr_flags |= DR_LOOPTST;
        !           620:                printf(" OK..\n\tDMA end of range interrupt...");
        !           621:                goto dmain;
        !           622:        }
        !           623:        printf(" OK..\n\tAttention interrupt....");
        !           624:        dr->dr_pulse = IENB|RDMA;
        !           625:        dr->dr_pulse = FCN2;
        !           626:        /* Wait for ATTN interrupt; DR_LOOPTST is false in dra->dr_flags*/
        !           627:        wait = 0;
        !           628:        while (dra->dr_flags & DR_LOOPTST) { 
        !           629:                result = dr->dr_cstat & 0xffff;
        !           630:                printf("\n\tWait for Attention intr...ISR:%lx",result);
        !           631:                if (++wait > 7) {
        !           632:                        printf("\n\t Attention interrupt timeout!!, ISR:%lx",
        !           633:                                result);
        !           634:                        dra->dr_flags &= ~DR_LOOPTST;
        !           635:                        return;
        !           636:                }
        !           637:        }
        !           638:        dra->dr_flags &= ~DR_LOOPTST;
        !           639:        printf(" OK..\n\tDone...");
        !           640: }
        !           641: 
        !           642: /* Reset state on Unibus reset */
        !           643: /*ARGSUSED*/
        !           644: drreset(uban)
        !           645:        int uban;
        !           646: {
        !           647: 
        !           648: }
        !           649: 
        !           650: /*
        !           651:  * An interrupt is caused either by an error,
        !           652:  * base address overflow, or transfer complete
        !           653:  */
        !           654: drintr(dr11)
        !           655:        int dr11;
        !           656: {
        !           657:        register struct dr_aux *dra = &dr_aux[dr11];
        !           658:        register struct rsdevice *rsaddr = RSADDR(dr11);
        !           659:        register struct buf *bp;
        !           660:        register short status;
        !           661: 
        !           662:        status = rsaddr->dr_cstat & 0xffff;     /* get board status register */
        !           663:        dra->dr_istat = status;
        !           664: #ifdef DR_DEBUG
        !           665:        if (DR11 & 2)
        !           666:                printf("\ndrintr: dr11 status : %lx",status & 0xffff);
        !           667: #endif
        !           668:        if (dra->dr_flags & DR_LOOPTST) {       /* doing loopback test */
        !           669:                dra->dr_flags &= ~DR_LOOPTST;
        !           670:                return;
        !           671:        }
        !           672:        /*
        !           673:         * Make sure this is not a stray interrupt; at least one of dmaf or attf
        !           674:         * must be set. Note that if the dr11 interrupt enable latch is reset 
        !           675:         * during a hardware interrupt ack sequence, and by the we get to this 
        !           676:         * point in the interrupt code it will be 0. This is done to give the
        !           677:         * programmer some control over how the two more-or-less independent
        !           678:         * interrupt sources on the board are handled.
        !           679:         * If the attention flag is set when drstrategy() is called to start a
        !           680:         * dma read or write an interrupt will be generated as soon as the
        !           681:         * strategy routine enables interrupts for dma end-of-range. This will
        !           682:         * cause execution of the interrupt routine (not necessarily bad) and
        !           683:         * will cause the interrupt enable mask to be reset (very bad since the
        !           684:         * dma end-of-range condition will not be able to generate an interrupt
        !           685:         * when it occurs) causing the dma operation to time-out (even though
        !           686:         * the dma transfer will be done successfully) or hang the process if a
        !           687:         * software time-out capability is not implemented. One way to avoid 
        !           688:         * this situation is to check for a pending attention interrupt (attf
        !           689:         * set) by calling drioctl() before doing a read or a write. For the
        !           690:         * time being this driver will solve the problem by clearing the attf
        !           691:         * flag in the status register before enabling interrupts in
        !           692:         * drstrategy().
        !           693:         *
        !           694:         * **** The IKON 10084 for which this driver is written will set both
        !           695:         * attf and dmaf if dma is terminated by an attention pulse. This will
        !           696:         * cause a wakeup(&dr_aux), which will be ignored since it is not being 
        !           697:         * waited on, and an iodone(bp) which is the desired action. Some other
        !           698:         * dr11 emulators, in particular the IKON 10077 for the Multibus, donot
        !           699:         * dmaf in this case. This may require some addtional code in the inter-
        !           700:         * rupt routine to ensure that en iodone(bp) is issued when dma is term-
        !           701:         * inated by attention.
        !           702:         */
        !           703:        bp = dra->dr_actf;
        !           704:        if ((status & (ATTF | DMAF)) == 0) {
        !           705:                printf("dr%d: stray interrupt, status=%x", dr11, status);
        !           706:                return;
        !           707:        }
        !           708:        if (status & DMAF) {            /* End-of-range interrupt */
        !           709:                dra->dr_flags |= DR_DMAX;
        !           710: 
        !           711: #ifdef DR_DEBUG
        !           712:                if (DR11 & 2)
        !           713:                printf("\ndrintr: e-o-r interrupt,cstat:%lx,dr_flags:%lx",
        !           714:                        status&0xffff, dra->dr_flags & DR_ACTV);
        !           715: #endif
        !           716:                if ((dra->dr_flags & DR_ACTV) == 0) {
        !           717:                        /* We are not doing DMA !! */
        !           718:                        bp->b_flags |= B_ERROR;
        !           719:                } else {
        !           720:                        if (dra->dr_op == DR_READ)
        !           721:                                mtpr(P1DC, bp->b_un.b_addr);
        !           722:                        dra->dr_bycnt -= bp->b_bcount;
        !           723:                        if (dra->dr_bycnt >0) {
        !           724:                                bp->b_un.b_addr += bp->b_bcount;
        !           725:                                bp->b_bcount = (dra->dr_bycnt > NBPG) ? NBPG:
        !           726:                                        dra->dr_bycnt;
        !           727:                                drstart(rsaddr, dra, bp);
        !           728:                                return;
        !           729:                        }
        !           730:                }
        !           731:                dra->dr_flags &= ~DR_ACTV;
        !           732:                wakeup((caddr_t)dra);           /* Wakeup waiting in drwait() */
        !           733:                rsaddr->dr_pulse = (RPER|RDMA|RATN); /* reset dma e-o-r flag */
        !           734:        }
        !           735:        /*
        !           736:         * Now test for attention interrupt -- It may be set in addition to 
        !           737:         * the dma e-o-r interrupt. If we get one we will issue a wakeup to
        !           738:         * the drioctl() routine which is presumable waiting for one.
        !           739:         * The program may have to monitor the attention interrupt received
        !           740:         * flag in addition to doing waits for the interrupt. Futhermore, 
        !           741:         * interrupts are not enabled unless dma is in progress or drioctl()
        !           742:         * has been called to wait for attention -- this may produce some
        !           743:         * strange results if attf is set on the dr11 when a read or a write
        !           744:         * is initiated, since that will enables interrupts.
        !           745:         * **** The appropriate code for this interrupt routine will probably
        !           746:         * be rather application dependent.
        !           747:         */
        !           748:        if (status & ATTF) {
        !           749:                dra->dr_flags |= DR_ATRX;
        !           750:                dra->dr_flags &= ~DR_ATWT;
        !           751:                rsaddr->dr_cstat = RATN;        /* reset attention flag */
        !           752:                /*
        !           753:                 * Some applications which use attention to terminate
        !           754:                 * dma may also want to issue an iodone() here to
        !           755:                 * wakeup physio().
        !           756:                 */
        !           757:                wakeup((caddr_t)&dra->dr_cmd);
        !           758:        }
        !           759: }
        !           760: 
        !           761: unsigned
        !           762: drminphys(bp)
        !           763:        struct buf *bp;
        !           764: {
        !           765: 
        !           766:        if (bp->b_bcount > 65536)
        !           767:                bp->b_bcount = 65536;
        !           768: }
        !           769: 
        !           770: /*
        !           771:  * This routine performs the device unique operations on the DR11W
        !           772:  * it is passed as an argument to and invoked by physio
        !           773:  */
        !           774: drstrategy (bp)
        !           775:        register struct buf *bp;
        !           776: {
        !           777:        register int s;
        !           778:        int unit = RSUNIT(bp->b_dev);
        !           779:        register struct rsdevice *rsaddr = RSADDR(unit);
        !           780:        register struct dr_aux *dra = &dr_aux[unit];
        !           781:        register int ok;
        !           782: #ifdef DR_DEBUG
        !           783:        register char *caddr;
        !           784:        long drva();
        !           785: #endif
        !           786: 
        !           787:        if ((dra->dr_flags & DR_OPEN) == 0) {   /* Device not open */
        !           788:                bp->b_error = ENXIO;
        !           789:                bp->b_flags |= B_ERROR;
        !           790:                iodone (bp);
        !           791:                return;
        !           792:        }
        !           793:        while (dra->dr_flags & DR_ACTV)
        !           794:                /* Device is active; should never be in here... */
        !           795:                (void) tsleep((caddr_t)&dra->dr_flags, DRPRI, devio, 0);
        !           796:        dra->dr_actf = bp;
        !           797: #ifdef DR_DEBUG
        !           798:        drva(dra, bp->b_proc, bp->b_un.b_addr, bp->b_bcount);
        !           799: #endif
        !           800:        dra->dr_oba = bp->b_un.b_addr;  /* Save original addr, count */
        !           801:        dra->dr_obc = bp->b_bcount;
        !           802:        dra->dr_bycnt = bp->b_bcount;   /* Save xfer count used by drintr() */
        !           803:        if ((((long)bp->b_un.b_addr & 0x3fffffff) >> PGSHIFT) !=
        !           804:            ((((long)bp->b_un.b_addr & 0x3fffffff) + bp->b_bcount) >> PGSHIFT))
        !           805:                bp->b_bcount = NBPG - (((long)bp->b_un.b_addr) & PGOFSET);
        !           806:        dra->dr_flags |= DR_ACTV;       /* Mark active (use in intr handler) */
        !           807:        s = SPL_UP();
        !           808:        drstart(rsaddr,dra,bp);
        !           809:        splx(s);
        !           810:        ok = drwait(rsaddr,dra);
        !           811: #ifdef DR_DEBUG
        !           812:        if (DR11 & 0x40) {
        !           813:                caddr = (char *)dra->dr_oba;
        !           814:                if (dra->dr_op == DR_READ)
        !           815:                        printf("\nAfter read: (%lx)(%lx)",
        !           816:                            caddr[0]&0xff, caddr[1]&0xff);
        !           817:        }
        !           818: #endif
        !           819:        dra->dr_flags &= ~DR_ACTV;              /* Clear active flag */
        !           820:        bp->b_un.b_addr = dra->dr_oba;  /* Restore original addr, count */
        !           821:        bp->b_bcount = dra->dr_obc;
        !           822:        if (!ok)
        !           823:                bp->b_flags |= B_ERROR;
        !           824:        /* Mark buffer B_DONE,so physstrat() in ml/machdep.c won't sleep */
        !           825:        iodone(bp);                     
        !           826:        wakeup((caddr_t)&dra->dr_flags);
        !           827:        /*
        !           828:         * Return to the calling program (physio()). Physio() will sleep
        !           829:         * until awaken by a call to iodone() in the interupt handler --
        !           830:         * which will be called by the dispatcher when it receives dma
        !           831:         * end-of-range interrupt.
        !           832:         */
        !           833: }
        !           834: 
        !           835: drwait(rs, dr)
        !           836:        register struct rsdevice *rs;
        !           837:        register struct dr_aux *dr;
        !           838: {
        !           839:        int s;
        !           840: 
        !           841:        s = SPL_UP();
        !           842:        while (dr->dr_flags & DR_ACTV)
        !           843:                (void) tsleep((caddr_t)dr, DRPRI, devio, 0);
        !           844:        splx(s);
        !           845:        if (dr->dr_flags & DR_TMDM) {           /* DMA timed out */
        !           846:                dr->dr_flags &= ~DR_TMDM;
        !           847:                return (0);
        !           848:        }
        !           849:        if (rs->dr_cstat & (PERR|BERR|TERR)) {
        !           850:                dr->dr_actf->b_flags |= B_ERROR;
        !           851:                return (0);
        !           852:        }
        !           853:        dr->dr_flags &= ~DR_DMAX;
        !           854:        return (1);
        !           855: }
        !           856: 
        !           857: /*
        !           858:  *
        !           859:  * The lower 8-bit of tinfo is the minor device number, the
        !           860:  * remaining higher 8-bit is the current timout number
        !           861:  */
        !           862: drrwtimo(tinfo)
        !           863:        register u_long tinfo;
        !           864: {
        !           865:        register long unit = tinfo & 0xff;
        !           866:        register struct dr_aux *dr = &dr_aux[unit];
        !           867:        register struct rsdevice *rs = dr->dr_addr;
        !           868: 
        !           869:        /*
        !           870:         * If this is not the timeout that drwrite/drread is waiting
        !           871:         * for then we should just go away
        !           872:         */
        !           873:        if ((tinfo &~ 0xff) != (dr->currenttimo << 8))
        !           874:                return;
        !           875:        /* Mark the device timed out */
        !           876:        dr->dr_flags |= DR_TMDM;
        !           877:        dr->dr_flags &= ~DR_ACTV;
        !           878:        rs->dr_pulse = RMSK;                    /* Inihibit interrupt */
        !           879:        rs->dr_pulse = (RPER|RDMA|RATN|IENB);   /* Clear DMA logic */
        !           880:        /*
        !           881:         * Some applications will not issue a master after dma timeout,
        !           882:         * since doing so sends an INIT H pulse to the external device,
        !           883:         * which may produce undesirable side-effects.
        !           884:         */
        !           885:        /* Wake up process waiting in drwait() and flag the error */
        !           886:        dr->dr_actf->b_flags |= B_ERROR;
        !           887:        wakeup((caddr_t)dr->dr_cmd);
        !           888: }
        !           889: 
        !           890: /*
        !           891:  * Kick the driver every second
        !           892:  */
        !           893: drtimo(dev)
        !           894:        dev_t dev;
        !           895: {
        !           896:        register int unit = RSUNIT(dev);
        !           897:        register struct dr_aux *dr;
        !           898: 
        !           899:        dr = &dr_aux[unit];
        !           900:        if (dr->dr_flags & DR_OPEN)
        !           901:                timeout(drtimo, (caddr_t)dev, hz);
        !           902:        wakeup((caddr_t)dr);    /* Wakeup any process waiting for interrupt */
        !           903: }
        !           904: 
        !           905: #ifdef DR_DEBUG
        !           906: drva(dra, p, va, bcnt)
        !           907:        struct dr_aux *dra;
        !           908:        struct proc *p;
        !           909:        char *va;
        !           910:        long bcnt;
        !           911: {
        !           912:        register long first, last , np;
        !           913: 
        !           914:        if (DR11 & 0x20)  {
        !           915:                first = ((long)(vtoph(p, (unsigned)va))) >> 10;
        !           916:                last = ((long)(vtoph(p, (unsigned)va+bcnt))) >> 10;
        !           917:                np = bcnt / 0x3ff;
        !           918:                printf("\ndrva: (op:%ld)(first:%ld)(last:%ld)(np:%ld)(cnt:%ld)",
        !           919:                        dra->dr_op,first,last,np,bcnt);
        !           920:        }
        !           921: }
        !           922: #endif
        !           923: 
        !           924: drstart(rsaddr, dra, bp)
        !           925:        register struct rsdevice *rsaddr;
        !           926:        register struct dr_aux *dra;
        !           927:        register struct buf *bp;
        !           928: {
        !           929:        register long addr;
        !           930:        u_short go;
        !           931: 
        !           932: #ifdef DR_DEBUG
        !           933:        if (dra->dr_op == DR_READ && (DR11 & 8)) {
        !           934:                char *caddr = (char *)bp->b_un.b_addr;
        !           935:                printf("\ndrstart: READ, bcnt:%ld",bp->b_bcount);
        !           936:                printf(",(%lx)(%lx)",caddr[0]&0xff,caddr[1]&0xff);
        !           937:        }
        !           938: #endif
        !           939:        /* we are doing raw IO, bp->b_un.b_addr is user's address */
        !           940:        addr = (long)vtoph(bp->b_proc, (unsigned)bp->b_un.b_addr);
        !           941:        /*
        !           942:         * Set DMA address into DR11 interace registers: DR11 requires that
        !           943:         * the address be right shifted 1 bit position before it is written
        !           944:         * to the board (The board will left shift it one bit position before
        !           945:         * it places the address on the bus
        !           946:         */
        !           947:        rsaddr->dr_walo = (addr >> 1) & 0xffff;
        !           948:        rsaddr->dr_wahi = (addr >> 17) & 0x7fff;
        !           949:        /* Set DMA range count: (number of words - 1) */
        !           950:        rsaddr->dr_range = (bp->b_bcount >> 1) - 1;
        !           951:        /* Set address modifier code to be used for DMA access to memory */
        !           952:        rsaddr->dr_addmod = DRADDMOD;
        !           953:        /*
        !           954:         * Now determine whether this is a read or a write. ***** This is
        !           955:         * probably only usefull for link mode operation, since dr11 doesnot
        !           956:         * controll the direction of data transfer. The C1 control input 
        !           957:         * controls whether the hardware is doing a read or a write. In link
        !           958:         * mode this is controlled by function 1 latch (looped back by the
        !           959:         * cable) and could be set the program. In the general case, the dr11
        !           960:         * doesnot know in advance what the direction of transfer is - although
        !           961:         * the program and protocol logic probably is
        !           962:         */
        !           963: #ifdef DR_DEBUG
        !           964:        if (DR11 & 1)
        !           965:                printf(
        !           966: "\ndrstrat: about to GO..,dr_cmd:%lx,drstat:%lx,drcnt:%ld,cdata:%lx,OP:%ld",
        !           967:                    dra->dr_cmd, rsaddr->dr_cstat, rsaddr->dr_range,
        !           968:                    rsaddr->dr_data, dra->dr_op);
        !           969: #endif
        !           970:        /*
        !           971:         * Update function latches may have been done already by drioctl() if
        !           972:         * request from drioctl()
        !           973:         */
        !           974:        if (dra->dr_cmd & DR_DFCN) {            /* deferred function write */
        !           975:                dra->dr_cmd &= ~DR_DFCN;        /* Clear request */
        !           976:                go = dra->dr_cmd & DR_FMSK;     /* mask out fcn bits */
        !           977:                rsaddr->dr_cstat = go;          /* Write it to the board */
        !           978:        }
        !           979:        /* Clear dmaf and attf to assure a clean dma start */
        !           980:        rsaddr->dr_pulse = RATN|RDMA|RPER;
        !           981:        rsaddr->dr_cstat = IENB|GO|CYCL|dra->dr_op; /* GO...... */
        !           982:        /*
        !           983:         * Now check for software cycle request -- usually
        !           984:         * by transmitter in link mode.
        !           985:         */
        !           986:        if (dra->dr_cmd & DR_PCYL) {
        !           987:                dra->dr_cmd &= ~DR_PCYL;        /* Clear request */
        !           988:                rsaddr->dr_pulse = CYCL;        /* Use pulse register again */
        !           989:        }
        !           990:        /*
        !           991:         * Now check for deferred ACLO FCNT2 pulse request -- usually to tell
        !           992:         * the transmitter (via its attention) that we have enabled dma.
        !           993:         */
        !           994:        if (dra->dr_cmd & DR_DACL) {
        !           995:                dra->dr_cmd &= ~DR_DACL;        /* Clear request */
        !           996:                rsaddr->dr_pulse = FCN2;        /* Use pulse register again */
        !           997:        }
        !           998: }
        !           999: #endif  NDR

unix.superglobalmegacorp.com

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