Annotation of 41BSD/4.0.upgrade/sys/dev/mba.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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