Annotation of cci/sys/vba/dr.c, revision 1.1.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.