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

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

unix.superglobalmegacorp.com

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