Annotation of 43BSDReno/sys/tahoevba/dr.c, revision 1.1.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.