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

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

unix.superglobalmegacorp.com

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