Annotation of 43BSDTahoe/sys/vaxmba/mba.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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