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

1.1       root        1: /*     uba.c   4.42    82/03/31        */
                      2: 
                      3: #include "../h/param.h"
                      4: #include "../h/systm.h"
                      5: #include "../h/cpu.h"
                      6: #include "../h/map.h"
                      7: #include "../h/pte.h"
                      8: #include "../h/buf.h"
                      9: #include "../h/vm.h"
                     10: #include "../h/ubareg.h"
                     11: #include "../h/ubavar.h"
                     12: #include "../h/dir.h"
                     13: #include "../h/user.h"
                     14: #include "../h/proc.h"
                     15: #include "../h/conf.h"
                     16: #include "../h/mtpr.h"
                     17: #include "../h/nexus.h"
                     18: #include "../h/dk.h"
                     19: #include "../h/trace.h"
                     20: 
                     21: #if VAX780
                     22: char   ubasr_bits[] = UBASR_BITS;
                     23: #endif
                     24: 
                     25: /*
                     26:  * Do transfer on device argument.  The controller
                     27:  * and uba involved are implied by the device.
                     28:  * We queue for resource wait in the uba code if necessary.
                     29:  * We return 1 if the transfer was started, 0 if it was not.
                     30:  * If you call this routine with the head of the queue for a
                     31:  * UBA, it will automatically remove the device from the UBA
                     32:  * queue before it returns.  If some other device is given
                     33:  * as argument, it will be added to the request queue if the
                     34:  * request cannot be started immediately.  This means that
                     35:  * passing a device which is on the queue but not at the head
                     36:  * of the request queue is likely to be a disaster.
                     37:  */
                     38: ubago(ui)
                     39:        register struct uba_device *ui;
                     40: {
                     41:        register struct uba_ctlr *um = ui->ui_mi;
                     42:        register struct uba_hd *uh;
                     43:        register int s, unit;
                     44: 
                     45:        uh = &uba_hd[um->um_ubanum];
                     46:        s = spl6();
                     47:        if (um->um_driver->ud_xclu && uh->uh_users > 0 || uh->uh_xclu)
                     48:                goto rwait;
                     49:        /* if(uh->uh_users < 0)
                     50:                printf ("(1) uh_users = %d\n", uh->uh_users); */
                     51:        if(um->um_tab.b_actf == NULL) {
                     52:                panic("null ptr in ubago\n");
                     53:                splx(s);
                     54:                return;
                     55:        }
                     56:        um->um_ubinfo = ubasetup(um->um_ubanum, um->um_tab.b_actf->b_actf,
                     57:            UBA_NEEDBDP|UBA_CANTWAIT);
                     58:        if (um->um_ubinfo == 0)
                     59:                goto rwait;
                     60:        uh->uh_users++;
                     61:        trace(TR_BDPOFF, -1, uh->uh_users);     /* overloaded lazy */
                     62:        if (um->um_driver->ud_xclu)
                     63:                uh->uh_xclu = 1;
                     64:        splx(s);
                     65:        if (ui->ui_dk >= 0) {
                     66:                unit = ui->ui_dk;
                     67:                dk_busy |= 1<<unit;
                     68:                dk_xfer[unit]++;
                     69:                dk_wds[unit] += um->um_tab.b_actf->b_actf->b_bcount>>6;
                     70:        }
                     71:        if (uh->uh_actf == ui)
                     72:                uh->uh_actf = ui->ui_forw;
                     73:        /* if(uh->uh_users <= 0)
                     74:                printf ("(2) uh_users = %d\n", uh->uh_users); */
                     75:        (*um->um_driver->ud_dgo)(um);
                     76:        return (1);
                     77: rwait:
                     78:        trace(TR_BDPOFF, -3, uh->uh_users);
                     79:        if (uh->uh_actf != ui) {
                     80:                ui->ui_forw = NULL;
                     81:                if (uh->uh_actf == NULL)
                     82:                        uh->uh_actf = ui;
                     83:                else
                     84:                        uh->uh_actl->ui_forw = ui;
                     85:                uh->uh_actl = ui;
                     86:        }
                     87:        splx(s);
                     88:        return (0);
                     89: }
                     90: 
                     91: ubadone(um)
                     92:        register struct uba_ctlr *um;
                     93: {
                     94:        register struct uba_hd *uh = &uba_hd[um->um_ubanum];
                     95: 
                     96:        if (um->um_driver->ud_xclu)
                     97:                uh->uh_xclu = 0;
                     98:        uh->uh_users--;
                     99:        trace(TR_BDPOFF, -2, uh->uh_users);     /* overloaded lazy */
                    100:        /* if(uh->uh_users < 0)
                    101:                printf ("(3) uh_users = %d\n", uh->uh_users); */
                    102:        ubarelse(um->um_ubanum, &um->um_ubinfo);
                    103: }
                    104: 
                    105: /*
                    106:  * Allocate and setup UBA map registers, and bdp's
                    107:  * Flags says whether bdp is needed, whether the caller can't
                    108:  * wait (e.g. if the caller is at interrupt level).
                    109:  *
                    110:  * Return value:
                    111:  *     Bits 0-8        Byte offset
                    112:  *     Bits 9-17       Start map reg. no.
                    113:  *     Bits 18-27      No. mapping reg's
                    114:  *     Bits 28-31      BDP no.
                    115:  */
                    116: ubasetup(uban, bp, flags)
                    117:        struct buf *bp;
                    118: {
                    119:        register struct uba_hd *uh = &uba_hd[uban];
                    120:        register int temp, i;
                    121:        int npf, reg, bdp;
                    122:        unsigned v;
                    123:        register struct pte *pte, *io;
                    124:        struct proc *rp;
                    125:        int a, o, ubinfo;
                    126: 
                    127: #if VAX7ZZ
                    128:        if (cpu == VAX_7ZZ)
                    129:                flags &= ~UBA_NEEDBDP;
                    130: #endif
                    131:        v = btop(bp->b_un.b_addr);
                    132:        o = (int)bp->b_un.b_addr & PGOFSET;
                    133:        npf = btoc(bp->b_bcount + o) + 1;
                    134:        a = spl6();
                    135:        while ((reg = rmalloc(uh->uh_map, npf)) == 0) {
                    136:                if (flags & UBA_CANTWAIT) {
                    137:                        splx(a);
                    138:                        return (0);
                    139:                }
                    140:                uh->uh_mrwant++;
                    141:                sleep((caddr_t)uh->uh_map, PSWP);
                    142:        }
                    143:        bdp = 0;
                    144:        if (flags & UBA_NEEDBDP) {
                    145:                while ((bdp = ffs(uh->uh_bdpfree)) == 0) {
                    146:                        if (flags & UBA_CANTWAIT) {
                    147:                                rmfree(uh->uh_map, npf, reg);
                    148:                                splx(a);
                    149:                                return (0);
                    150:                        }
                    151:                        uh->uh_bdpwant++;
                    152:                        sleep((caddr_t)uh->uh_map, PSWP);
                    153:                }
                    154:                uh->uh_bdpfree &= ~(1 << (bdp-1));
                    155:        } else if (flags & UBA_HAVEBDP)
                    156:                bdp = (flags >> 28) & 0xf;
                    157:        else if(flags & UBA_WANTBDP) {
                    158:                bdp = ffs(uh->uh_bdpfree);
                    159:                if(bdp)
                    160:                        uh->uh_bdpfree &= ~(1 << (bdp-1));
                    161:        }
                    162:        trace(TR_BDPON, uh->uh_bdpfree, flags);
                    163:        splx(a);
                    164:        reg--;
                    165:        ubinfo = (bdp << 28) | (npf << 18) | (reg << 9) | o;
                    166:        temp = (bdp << 21) | UBAMR_MRV;
                    167:        if (bdp && (o & 01))
                    168:                temp |= UBAMR_BO;
                    169:        rp = bp->b_flags&B_DIRTY ? &proc[2] : bp->b_proc;
                    170:        if ((bp->b_flags & B_PHYS) == 0)
                    171:                pte = &Sysmap[btop(((int)bp->b_un.b_addr)&0x7fffffff)];
                    172:        else if (bp->b_flags & B_UAREA)
                    173:                pte = &rp->p_addr[v];
                    174:        else if (bp->b_flags & B_PAGET)
                    175:                pte = &Usrptmap[btokmx((struct pte *)bp->b_un.b_addr)];
                    176:        else
                    177:                pte = vtopte(rp, v);
                    178:        io = &uh->uh_uba->uba_map[reg];
                    179:        while (--npf != 0) {
                    180:                if (pte->pg_pfnum == 0)
                    181:                        panic("uba zero uentry");
                    182:                *(int *)io++ = pte++->pg_pfnum | temp;
                    183:        }
                    184:        *(int *)io++ = 0;
                    185:        return (ubinfo);
                    186: }
                    187: 
                    188: /*
                    189:  * Non buffer setup interface... set up a buffer and call ubasetup.
                    190:  */
                    191: uballoc(uban, addr, bcnt, flags)
                    192:        int uban;
                    193:        caddr_t addr;
                    194:        int bcnt, flags;
                    195: {
                    196:        struct buf ubabuf;
                    197: 
                    198:        ubabuf.b_un.b_addr = addr;
                    199:        ubabuf.b_flags = B_BUSY;
                    200:        ubabuf.b_bcount = bcnt;
                    201:        /* that's all the fields ubasetup() needs */
                    202:        return (ubasetup(uban, &ubabuf, flags));
                    203: }
                    204:  
                    205: /*
                    206:  * Release resources on uba uban, and then unblock resource waiters.
                    207:  * The map register parameter is by value since we need to block
                    208:  * against uba resets on 11/780's.
                    209:  */
                    210: ubarelse(uban, amr)
                    211:        int *amr;
                    212: {
                    213:        register struct uba_hd *uh = &uba_hd[uban];
                    214:        register int bdp, reg, npf, s;
                    215:        int mr;
                    216:  
                    217:        /*
                    218:         * Carefully see if we should release the space, since
                    219:         * it may be released asynchronously at uba reset time.
                    220:         */
                    221:        s = spl6();
                    222:        mr = *amr;
                    223:        if (mr == 0) {
                    224:                /*
                    225:                 * A ubareset() occurred before we got around
                    226:                 * to releasing the space... no need to bother.
                    227:                 */
                    228:                splx(s);
                    229:                return;
                    230:        }
                    231:        *amr = 0;
                    232:        splx(s);                /* let interrupts in, we're safe for a while */
                    233:        bdp = (mr >> 28) & 0x0f;
                    234:        if (bdp) {
                    235:                switch (cpu) {
                    236: #if VAX780
                    237:                case VAX_780:
                    238:                        uh->uh_uba->uba_dpr[bdp] |= UBADPR_BNE;
                    239:                        break;
                    240: #endif
                    241: #if VAX750
                    242:                case VAX_750:
                    243:                        uh->uh_uba->uba_dpr[bdp] |=
                    244:                            UBADPR_PURGE|UBADPR_NXM|UBADPR_UCE;
                    245:                        break;
                    246: #endif
                    247:                }
                    248:                uh->uh_bdpfree |= 1 << (bdp-1);         /* atomic */
                    249:                trace(TR_BDPOFF, uh->uh_bdpfree, 0);
                    250:                if (uh->uh_bdpwant) {
                    251:                        uh->uh_bdpwant = 0;
                    252:                        wakeup((caddr_t)uh->uh_map);
                    253:                }
                    254:        }
                    255:        /*
                    256:         * Put back the registers in the resource map.
                    257:         * The map code must not be reentered, so we do this
                    258:         * at high ipl.
                    259:         */
                    260:        npf = (mr >> 18) & 0x3ff;
                    261:        reg = ((mr >> 9) & 0x1ff) + 1;
                    262:        s = spl6();
                    263:        rmfree(uh->uh_map, npf, reg);
                    264:        splx(s);
                    265: 
                    266:        /*
                    267:         * Wakeup sleepers for map registers,
                    268:         * and also, if there are processes blocked in dgo(),
                    269:         * give them a chance at the UNIBUS.
                    270:         */
                    271:        if (uh->uh_mrwant) {
                    272:                uh->uh_mrwant = 0;
                    273:                wakeup((caddr_t)uh->uh_map);
                    274:        }
                    275:        while (uh->uh_actf && ubago(uh->uh_actf))
                    276:                ;
                    277: }
                    278: 
                    279: #define        PRGTIM  10      /* time to spin for bdp flush on comet */
                    280: 
                    281: ubapurge(um)
                    282:        register struct uba_ctlr *um;
                    283: {
                    284:        register struct uba_hd *uh = um->um_hd;
                    285:        register int bdp = (um->um_ubinfo >> 28) & 0x0f;
                    286:        register int i;
                    287:        register int *reg;
                    288: 
                    289:        switch (cpu) {
                    290: #if VAX780
                    291:        case VAX_780:
                    292:                uh->uh_uba->uba_dpr[bdp] |= UBADPR_BNE;
                    293:                break;
                    294: #endif
                    295: #if VAX750
                    296:        case VAX_750:
                    297:                reg = &uh->uh_uba->uba_dpr[bdp];
                    298:                *reg |= UBADPR_PURGE|UBADPR_NXM|UBADPR_UCE;
                    299:                for (i = PRGTIM; i > 0; i--)
                    300:                        if ((*reg & UBADPR_PURGE) == 0)
                    301:                                break;
                    302:                if (i <= 0)
                    303:                        printf("uba%d bdp%d stuck\n", um->um_ubanum, bdp);
                    304:                if (*reg & UBADPR_ERROR)
                    305:                        printf("uba%d bdp%d error %x\n", um->um_ubanum,
                    306:                                bdp, *reg);
                    307:                break;
                    308: #endif
                    309:        }
                    310: }
                    311: 
                    312: /*
                    313:  * Generate a reset on uba number uban.  Then
                    314:  * call each device in the character device table,
                    315:  * giving it a chance to clean up so as to be able to continue.
                    316:  */
                    317: ubareset(uban)
                    318:        int uban;
                    319: {
                    320:        register struct cdevsw *cdp;
                    321:        register struct uba_hd *uh = &uba_hd[uban];
                    322:        int s;
                    323: 
                    324:        s = spl6();
                    325:        uh->uh_users = 0;
                    326:        uh->uh_zvcnt = 0;
                    327:        uh->uh_xclu = 0;
                    328:        uh->uh_hangcnt = 0;
                    329:        uh->uh_actf = uh->uh_actl = 0;
                    330:        uh->uh_bdpwant = 0;
                    331:        uh->uh_mrwant = 0;
                    332:        wakeup((caddr_t)&uh->uh_bdpwant);
                    333:        wakeup((caddr_t)&uh->uh_mrwant);
                    334:        printf("uba%d: reset", uban);
                    335:        ubainit(uh->uh_uba);
                    336:        for (cdp = cdevsw; cdp->d_open; cdp++)
                    337:                (*cdp->d_reset)(uban);
                    338: #ifdef INET
                    339:        ifubareset(uban);
                    340: #endif
                    341:        printf("\n");
                    342:        splx(s);
                    343: }
                    344: 
                    345: /*
                    346:  * Init a uba.  This is called with a pointer
                    347:  * rather than a virtual address since it is called
                    348:  * by code which runs with memory mapping disabled.
                    349:  * In these cases we really don't need the interrupts
                    350:  * enabled, but since we run with ipl high, we don't care
                    351:  * if they are, they will never happen anyways.
                    352:  */
                    353: ubainit(uba)
                    354:        register struct uba_regs *uba;
                    355: {
                    356: 
                    357:        switch (cpu) {
                    358: #if VAX780
                    359:        case VAX_780:
                    360:                uba->uba_cr = UBACR_ADINIT;
                    361:                uba->uba_cr = UBACR_IFS|UBACR_BRIE|UBACR_USEFIE|UBACR_SUEFIE;
                    362:                while ((uba->uba_cnfgr & UBACNFGR_UBIC) == 0)
                    363:                        ;
                    364:                break;
                    365: #endif
                    366: #if VAX750
                    367:        case VAX_750:
                    368: #endif
                    369: #if VAX7ZZ
                    370:        case VAX_7ZZ:
                    371: #endif
                    372: #if defined(VAX750) || defined(VAX7ZZ)
                    373:                mtpr(IUR, 0);
                    374:                /* give devices time to recover from power fail */
                    375: /* THIS IS PROBABLY UNNECESSARY */
                    376:                DELAY(500000);
                    377: /* END PROBABLY UNNECESSARY */
                    378:                break;
                    379: #endif
                    380:        }
                    381: }
                    382: 
                    383: #if VAX780
                    384: /*
                    385:  * Check to make sure the UNIBUS adaptor is not hung,
                    386:  * with an interrupt in the register to be presented,
                    387:  * but not presenting it for an extended period (5 seconds).
                    388:  */
                    389: unhang()
                    390: {
                    391:        register int uban;
                    392: 
                    393:        for (uban = 0; uban < numuba; uban++) {
                    394:                register struct uba_hd *uh = &uba_hd[uban];
                    395:                register struct uba_regs *up = uh->uh_uba;
                    396: 
                    397:                if (up->uba_sr == 0)
                    398:                        return;
                    399:                up->uba_sr = UBASR_CRD|UBASR_LEB;
                    400:                uh->uh_hangcnt++;
                    401:                if (uh->uh_hangcnt > 5*hz) {
                    402:                        uh->uh_hangcnt = 0;
                    403:                        printf("uba%d: hung\n", uban);
                    404:                        ubareset(uban);
                    405:                }
                    406:        }
                    407: }
                    408: 
                    409: /*
                    410:  * This is a timeout routine which decrements the ``i forgot to
                    411:  * interrupt'' counts, on an 11/780.  This prevents slowly growing
                    412:  * counts from causing a UBA reset since we are interested only
                    413:  * in hang situations.
                    414:  */
                    415: ubawatch()
                    416: {
                    417:        register struct uba_hd *uh;
                    418:        register int uban;
                    419: 
                    420:        if (panicstr)
                    421:                return;
                    422:        for (uban = 0; uban < numuba; uban++) {
                    423:                uh = &uba_hd[uban];
                    424:                if (uh->uh_hangcnt)
                    425:                        uh->uh_hangcnt--;
                    426:        }
                    427: }
                    428: 
                    429: int    ubawedgecnt = 10;
                    430: int    ubacrazy = 500;
                    431: /*
                    432:  * This routine is called by the locore code to
                    433:  * process a UBA error on an 11/780.  The arguments are passed
                    434:  * on the stack, and value-result (through some trickery).
                    435:  * In particular, the uvec argument is used for further
                    436:  * uba processing so the result aspect of it is very important.
                    437:  * It must not be declared register.
                    438:  */
                    439: /*ARGSUSED*/
                    440: ubaerror(uban, uh, xx, uvec, uba)
                    441:        register int uban;
                    442:        register struct uba_hd *uh;
                    443:        int uvec;
                    444:        register struct uba_regs *uba;
                    445: {
                    446:        register sr, s;
                    447: 
                    448:        if (uvec == 0) {
                    449:                uh->uh_zvcnt++;
                    450:                if (uh->uh_zvcnt > 250000) {
                    451:                        printf("uba%d: too many zero vectors\n");
                    452:                        ubareset(uban);
                    453:                }
                    454:                uvec = 0;
                    455:                return;
                    456:        }
                    457:        if (uba->uba_cnfgr & NEX_CFGFLT) {
                    458:                printf("uba%d: sbi fault sr=%b cnfgr=%b\n",
                    459:                    uban, uba->uba_sr, ubasr_bits,
                    460:                    uba->uba_cnfgr, NEXFLT_BITS);
                    461:                ubareset(uban);
                    462:                uvec = 0;
                    463:                return;
                    464:        }
                    465:        sr = uba->uba_sr;
                    466:        s = spl7();
                    467:        printf("uba%d: uba error sr=%b fmer=%x fubar=%o\n",
                    468:            uban, uba->uba_sr, ubasr_bits, uba->uba_fmer, 4*uba->uba_fubar);
                    469:        splx(s);
                    470:        uba->uba_sr = sr;
                    471:        uvec &= UBABRRVR_DIV;
                    472:        if (++uh->uh_errcnt % ubawedgecnt == 0) {
                    473:                if (uh->uh_errcnt > ubacrazy)
                    474:                        panic("uba crazy");
                    475:                printf("ERROR LIMIT ");
                    476:                ubareset(uban);
                    477:                uvec = 0;
                    478:                return;
                    479:        }
                    480:        return;
                    481: }
                    482: #endif
                    483: 
                    484: #if    defined(CHAOS)
                    485: /*
                    486:  * This routine allows remapping of previously
                    487:  * allocated UNIBUS bdp and map resources
                    488:  * onto different memory addresses.
                    489:  * It should only be used by routines which need
                    490:  * small fixed length mappings for long periods of time
                    491:  * (like the ARPANET ACC IMP interface).
                    492:  * It only maps kernel addresses.
                    493:  */
                    494: ubaremap(uban, ubinfo, addr)
                    495:        int uban;
                    496:        register unsigned ubinfo;
                    497:        caddr_t addr;
                    498: {
                    499:        register struct uba_hd *uh = &uba_hd[uban];
                    500:        register struct pte *pte, *io;
                    501:        register int temp, bdp;
                    502:        int npf, o;
                    503: 
                    504:        o = (int)addr & PGOFSET;
                    505:        bdp = (ubinfo >> 28) & 0xf;
                    506:        npf = (ubinfo >> 18) & 0x3ff;
                    507:        io = &uh->uh_uba->uba_map[(ubinfo >> 9) & 0x1ff];
                    508:        temp = (bdp << 21) | UBAMR_MRV;
                    509: 
                    510:        /*
                    511:         * If using buffered data path initiate purge
                    512:         * of old data and set byte offset bit if next
                    513:         * transfer will be from odd address.
                    514:         */
                    515:        if (bdp) {
                    516:                switch (cpu) {
                    517: #if VAX780
                    518:                case VAX_780:
                    519:                        uh->uh_uba->uba_dpr[bdp] |= UBADPR_BNE;
                    520:                        break;
                    521: #endif
                    522: #if VAX750
                    523:                case VAX_750:
                    524:                        uh->uh_uba->uba_dpr[bdp] |=
                    525:                            UBADPR_PURGE|UBADPR_NXM|UBADPR_UCE;
                    526:                        break;
                    527: #endif
                    528:                }
                    529:                if (o & 1)
                    530:                        temp |= UBAMR_BO;
                    531:        }
                    532: 
                    533:        /*
                    534:         * Set up the map registers, leaving an invalid reg
                    535:         * at the end to guard against wild unibus transfers.
                    536:         */
                    537:        pte = &Sysmap[btop(((int)addr)&0x7fffffff)];
                    538:        while (--npf != 0)
                    539:                *(int *)io++ = pte++->pg_pfnum | temp;
                    540:        *(int *)io = 0;
                    541: 
                    542:        /*
                    543:         * Return effective UNIBUS address.
                    544:         */
                    545:        return ((ubinfo & ~PGOFSET) | o);
                    546: }
                    547: #endif defined(CHAOS)

unix.superglobalmegacorp.com

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