Annotation of 43BSDTahoe/sys/tahoevba/dr.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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