Annotation of cci/sys/vba/dr.c, revision 1.1

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

unix.superglobalmegacorp.com

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