Annotation of researchv8dc/sys/dev/mba.c, revision 1.1.1.1

1.1       root        1: /*     mba.c   4.20    81/05/09        */
                      2: 
                      3: #include "mba.h"
                      4: #if NMBA > 0
                      5: /*
                      6:  * Massbus driver, arbitrates a massbus among attached devices.
                      7:  */
                      8: #include "../h/param.h"
                      9: #include "../h/systm.h"
                     10: #include "../h/dk.h"
                     11: #include "../h/buf.h"
                     12: #include "../h/conf.h"
                     13: #include "../h/dir.h"
                     14: #include "../h/user.h"
                     15: #include "../h/proc.h"
                     16: #include "../h/map.h"
                     17: #include "../h/pte.h"
                     18: #include "../h/mbareg.h"
                     19: #include "../h/mbavar.h"
                     20: #include "../h/mtpr.h"
                     21: #include "../h/vm.h"
                     22: 
                     23: char   mbsr_bits[] = MBSR_BITS;
                     24: 
                     25: #define MTRDREV 1      /* enable mag tape read backwards error recovery */
                     26: 
                     27: /*
                     28:  * Start activity on a massbus device.
                     29:  * We are given the device's mba_device structure and activate
                     30:  * the device via the unit start routine.  The unit start
                     31:  * routine may indicate that it is finished (e.g. if the operation
                     32:  * was a ``sense'' on a tape drive), that the (multi-ported) unit
                     33:  * is busy (we will get an interrupt later), that it started the
                     34:  * unit (e.g. for a non-data transfer operation), or that it has
                     35:  * set up a data transfer operation and we should start the massbus adaptor.
                     36:  */
                     37: mbustart(mi)
                     38:        register struct mba_device *mi;
                     39: {
                     40:        register struct buf *bp;        /* i/o operation at head of queue */
                     41:        register struct mba_hd *mhp;    /* header for mba device is on */
                     42: 
                     43: loop:
                     44:        /*
                     45:         * Get the first thing to do off device queue.
                     46:         */
                     47:        bp = mi->mi_tab.b_actf;
                     48:        if (bp == NULL)
                     49:                return;
                     50:        /*
                     51:         * Let the drivers unit start routine have at it
                     52:         * and then process the request further, per its instructions.
                     53:         */
                     54:        switch ((*mi->mi_driver->md_ustart)(mi)) {
                     55: 
                     56:        case MBU_NEXT:          /* request is complete (e.g. ``sense'') */
                     57:                mi->mi_tab.b_active = 0;
                     58:                mi->mi_tab.b_errcnt = 0;
                     59:                mi->mi_tab.b_actf = bp->av_forw;
                     60:                iodone(bp);
                     61:                goto loop;
                     62: 
                     63:        case MBU_DODATA:        /* all ready to do data transfer */
                     64:                /*
                     65:                 * Queue the device mba_device structure on the massbus
                     66:                 * mba_hd structure for processing as soon as the
                     67:                 * data path is available.
                     68:                 */
                     69:                mhp = mi->mi_hd;
                     70:                mi->mi_forw = NULL;
                     71:                if (mhp->mh_actf == NULL)
                     72:                        mhp->mh_actf = mi;
                     73:                else
                     74:                        mhp->mh_actl->mi_forw = mi;
                     75:                mhp->mh_actl = mi;
                     76:                /*
                     77:                 * If data path is idle, start transfer now.
                     78:                 * In any case the device is ``active'' waiting for the
                     79:                 * data to transfer.
                     80:                 */
                     81:                mi->mi_tab.b_active = 1;
                     82:                if (mhp->mh_active == 0)
                     83:                        mbstart(mhp);
                     84:                return;
                     85: 
                     86:        case MBU_STARTED:       /* driver started a non-data transfer */
                     87:                /*
                     88:                 * Mark device busy during non-data transfer
                     89:                 * and count this as a ``seek'' on the device.
                     90:                 */
                     91:                if (mi->mi_dk >= 0) {
                     92:                        dk_seek[mi->mi_dk]++;
                     93:                        dk_busy |= (1 << mi->mi_dk);
                     94:                }
                     95:                mi->mi_tab.b_active = 1;
                     96:                return;
                     97: 
                     98:        case MBU_BUSY:          /* dual port drive busy */
                     99:                /*
                    100:                 * We mark the device structure so that when an
                    101:                 * interrupt occurs we will know to restart the unit.
                    102:                 */
                    103:                mi->mi_tab.b_flags |= B_BUSY;
                    104:                return;
                    105: 
                    106:        default:
                    107:                panic("mbustart");
                    108:        }
                    109: }
                    110: 
                    111: /*
                    112:  * Start an i/o operation on the massbus specified by the argument.
                    113:  * We peel the first operation off its queue and insure that the drive
                    114:  * is present and on-line.  We then use the drivers start routine
                    115:  * (if any) to prepare the drive, setup the massbus map for the transfer
                    116:  * and start the transfer.
                    117:  */
                    118: mbstart(mhp)
                    119:        register struct mba_hd *mhp;
                    120: {
                    121:        register struct mba_device *mi;
                    122:        struct buf *bp;
                    123:        register struct mba_regs *mbp;
                    124:        register int com;
                    125: 
                    126: loop:
                    127:        /*
                    128:         * Look for an operation at the front of the queue.
                    129:         */
                    130:        if ((mi = mhp->mh_actf) == NULL) {
                    131:                return;
                    132:        }
                    133:        if ((bp = mi->mi_tab.b_actf) == NULL) {
                    134:                mhp->mh_actf = mi->mi_forw;
                    135:                goto loop;
                    136:        }
                    137:        /*
                    138:         * If this device isn't present and on-line, then
                    139:         * we screwed up, and can't really do the operation.
                    140:         * Check only for non-tape drives, as the tape drivers
                    141:         * check ONLINE themselves.  Also, TU78 registers are different.
                    142:         */
                    143:        if ((mi->mi_drv->mbd_dt & MBDT_TAP) == 0)
                    144:        if ((mi->mi_drv->mbd_ds & MBDS_DREADY) != MBDS_DREADY) {
                    145:                printf("%s%d: not ready\n", mi->mi_driver->md_dname,
                    146:                    dkunit(bp));
                    147:                mi->mi_tab.b_actf = bp->av_forw;
                    148:                mi->mi_tab.b_errcnt = 0;
                    149:                mi->mi_tab.b_active = 0;
                    150:                bp->b_flags |= B_ERROR;
                    151:                iodone(bp);
                    152:                goto loop;
                    153:        }
                    154:        /*
                    155:         * We can do the operation; mark the massbus active
                    156:         * and let the device start routine setup any necessary
                    157:         * device state for the transfer (e.g. desired cylinder, etc
                    158:         * on disks).
                    159:         */
                    160:        mhp->mh_active = 1;
                    161:        if (mi->mi_driver->md_start) {
                    162:                if ((com = (*mi->mi_driver->md_start)(mi)) == 0)
                    163:                        com = (bp->b_flags & B_READ) ?
                    164:                            MB_RCOM|MB_GO : MB_WCOM|MB_GO;
                    165:        } else
                    166:                com = (bp->b_flags & B_READ) ? MB_RCOM|MB_GO : MB_WCOM|MB_GO;
                    167: 
                    168:        /*
                    169:         * Setup the massbus control and map registers and start
                    170:         * the transfer.
                    171:         */
                    172:        mbp = mi->mi_mba;
                    173:        mbp->mba_sr = -1;       /* conservative */
                    174: #ifdef MTRDREV
                    175:        if (bp->b_bcount >= 0) {
                    176:                mbp->mba_var = mbasetup(mi);
                    177:                mbp->mba_bcr = -bp->b_bcount;
                    178:        } else {
                    179:                mbp->mba_var = mbasetup(mi) - bp->b_bcount - 1;
                    180:                mbp->mba_bcr = bp->b_bcount;
                    181:        }
                    182: #else
                    183:        mbp->mba_var = mbasetup(mi);
                    184:        mbp->mba_bcr = -bp->b_bcount;
                    185: #endif
                    186:        mi->mi_drv->mbd_cs1 = com;
                    187:        if (mi->mi_dk >= 0) {
                    188:                dk_busy |= 1 << mi->mi_dk;
                    189:                dk_xfer[mi->mi_dk]++;
                    190: #ifdef MTRDREV
                    191:                if (bp->b_bcount >= 0)
                    192:                        dk_wds[mi->mi_dk] += bp->b_bcount >> 6;
                    193:                else
                    194:                        dk_wds[mi->mi_dk] += -(bp->b_bcount) >> 6;
                    195: #else
                    196:                dk_wds[mi->mi_dk] += bp->b_bcount >> 6;
                    197: #endif
                    198:        }
                    199: }
                    200: 
                    201: /*
                    202:  * Take an interrupt off of massbus mbanum,
                    203:  * and dispatch to drivers as appropriate.
                    204:  */
                    205: mbintr(mbanum)
                    206:        int mbanum;
                    207: {
                    208:        register struct mba_hd *mhp = &mba_hd[mbanum];
                    209:        register struct mba_regs *mbp = mhp->mh_mba;
                    210:        register struct mba_device *mi;
                    211:        register struct buf *bp;
                    212:        register int drive;
                    213:        int mbasr, as;
                    214:        
                    215:        /*
                    216:         * Read out the massbus status register
                    217:         * and attention status register and clear
                    218:         * the bits in same by writing them back.
                    219:         */
                    220:        mbasr = mbp->mba_sr;
                    221:        mbp->mba_sr = mbasr;
                    222: #if VAX750
                    223:        if (mbasr&MBSR_CBHUNG) {
                    224:                printf("mba%d: control bus hung\n", mbanum);
                    225:                panic("cbhung");
                    226:        }
                    227: #endif
                    228:        /* note: the mbd_as register is shared between drives */
                    229:        as = mbp->mba_drv[0].mbd_as & 0xff;
                    230:        mbp->mba_drv[0].mbd_as = as;
                    231: 
                    232:        /*
                    233:         * If the mba was active, process the data transfer
                    234:         * complete interrupt; otherwise just process units which
                    235:         * are now finished.
                    236:         */
                    237:        if (mhp->mh_active) {
                    238:                /*
                    239:                 * Clear attention status for drive whose data
                    240:                 * transfer related operation completed,
                    241:                 * and give the dtint driver
                    242:                 * routine a chance to say what is next.
                    243:                 */
                    244:                mi = mhp->mh_actf;
                    245:                as &= ~(1 << mi->mi_drive);
                    246:                dk_busy &= ~(1 << mi->mi_dk);
                    247:                bp = mi->mi_tab.b_actf;
                    248:                switch ((*mi->mi_driver->md_dtint)(mi, mbasr)) {
                    249: 
                    250:                case MBD_DONE:          /* all done, for better or worse */
                    251:                        /*
                    252:                         * Flush request from drive queue.
                    253:                         */
                    254:                        mi->mi_tab.b_errcnt = 0;
                    255:                        mi->mi_tab.b_actf = bp->av_forw;
                    256:                        iodone(bp);
                    257:                        /* fall into... */
                    258:                case MBD_RETRY:         /* attempt the operation again */
                    259:                        /*
                    260:                         * Dequeue data transfer from massbus queue;
                    261:                         * if there is still a i/o request on the device
                    262:                         * queue then start the next operation on the device.
                    263:                         * (Common code for DONE and RETRY).
                    264:                         */
                    265:                        mhp->mh_active = 0;
                    266:                        mi->mi_tab.b_active = 0;
                    267:                        mhp->mh_actf = mi->mi_forw;
                    268:                        if (mi->mi_tab.b_actf)
                    269:                                mbustart(mi);
                    270:                        break;
                    271: 
                    272:                case MBD_RESTARTED:     /* driver restarted op (ecc, e.g.)
                    273:                        /*
                    274:                         * Note that mhp->mh_active is still on.
                    275:                         */
                    276:                        break;
                    277: 
                    278:                default:
                    279:                        panic("mbintr");
                    280:                }
                    281:        }
                    282:        /*
                    283:         * Service drives which require attention
                    284:         * after non-data-transfer operations.
                    285:         */
                    286:        while (drive = ffs(as)) {
                    287:                drive--;                /* was 1 origin */
                    288:                as &= ~(1 << drive);
                    289:                mi = mhp->mh_mbip[drive];
                    290:                if (mi == NULL)
                    291:                        continue;
                    292:                /*
                    293:                 * If driver has a handler for non-data transfer
                    294:                 * interrupts, give it a chance to tell us what to do.
                    295:                 */
                    296:                if (mi->mi_driver->md_ndint) {
                    297:                        mi->mi_tab.b_active = 0;
                    298:                        switch ((*mi->mi_driver->md_ndint)(mi)) {
                    299: 
                    300:                        case MBN_DONE:          /* operation completed */
                    301:                                mi->mi_tab.b_errcnt = 0;
                    302:                                bp = mi->mi_tab.b_actf;
                    303:                                mi->mi_tab.b_actf = bp->av_forw;
                    304:                                iodone(bp);
                    305:                                /* fall into common code */
                    306:                        case MBN_RETRY:         /* operation continues */
                    307:                                if (mi->mi_tab.b_actf)
                    308:                                        mbustart(mi);
                    309:                                break;
                    310:                        case MBN_SKIP:          /* ignore unsol. interrupt */
                    311:                                break;
                    312:                        default:
                    313:                                panic("mbintr");
                    314:                        }
                    315:                } else
                    316:                        /*
                    317:                         * If there is no non-data transfer interrupt
                    318:                         * routine, then we should just
                    319:                         * restart the unit, leading to a mbstart() soon.
                    320:                         */
                    321:                        mbustart(mi);
                    322:        }
                    323:        /*
                    324:         * If there is an operation available and
                    325:         * the massbus isn't active, get it going.
                    326:         */
                    327:        if (mhp->mh_actf && !mhp->mh_active)
                    328:                mbstart(mhp);
                    329:        /* THHHHATS all folks... */
                    330: }
                    331: 
                    332: /*
                    333:  * Setup the mapping registers for a transfer.
                    334:  */
                    335: mbasetup(mi)
                    336:        register struct mba_device *mi;
                    337: {
                    338:        register struct mba_regs *mbap = mi->mi_mba;
                    339:        struct buf *bp = mi->mi_tab.b_actf;
                    340:        register int i;
                    341:        int npf;
                    342:        unsigned v;
                    343:        register struct pte *pte, *io;
                    344:        int o;
                    345:        int vaddr;
                    346:        struct proc *rp;
                    347: 
                    348:        io = mbap->mba_map;
                    349:        v = btop(bp->b_un.b_addr);
                    350:        o = (int)bp->b_un.b_addr & PGOFSET;
                    351: #ifdef MTRDREV
                    352:        if (bp->b_bcount >= 0)
                    353:                npf = btoc(bp->b_bcount + o);
                    354:        else
                    355:                npf = btoc(-(bp->b_bcount) + o);
                    356: #else
                    357:        npf = btoc(bp->b_bcount + o);
                    358: #endif
                    359:        rp = bp->b_flags&B_DIRTY ? &proc[2] : bp->b_proc;
                    360:        vaddr = o;
                    361:        if (bp->b_flags & B_UAREA) {
                    362:                for (i = 0; i < UPAGES; i++) {
                    363:                        if (rp->p_addr[i].pg_pfnum == 0)
                    364:                                panic("mba: zero upage");
                    365:                        *(int *)io++ = rp->p_addr[i].pg_pfnum | PG_V;
                    366:                }
                    367:        } else if ((bp->b_flags & B_PHYS) == 0) {
                    368:                pte = &Sysmap[btop(((int)bp->b_un.b_addr)&0x7fffffff)];
                    369:                while (--npf >= 0)
                    370:                        *(int *)io++ = pte++->pg_pfnum | PG_V;
                    371:        } else {
                    372:                if (bp->b_flags & B_PAGET)
                    373:                        pte = &Usrptmap[btokmx((struct pte *)bp->b_un.b_addr)];
                    374:                else
                    375:                        pte = vtopte(rp, v);
                    376:                while (--npf >= 0) {
                    377:                        if (pte->pg_pfnum == 0)
                    378:                                panic("mba, zero entry");
                    379:                        *(int *)io++ = pte++->pg_pfnum | PG_V;
                    380:                }
                    381:        }
                    382:        *(int *)io++ = 0;
                    383:        return (vaddr);
                    384: }
                    385: 
                    386: /*
                    387:  * Init and interrupt enable a massbus adapter.
                    388:  */
                    389: mbainit(mp)
                    390:        struct mba_regs *mp;
                    391: {
                    392: 
                    393:        mp->mba_cr = MBCR_INIT;
                    394:        mp->mba_cr = MBCR_IE;
                    395: }
                    396: #endif

unix.superglobalmegacorp.com

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