123352Smckusick /* 229248Smckusick * Copyright (c) 1982, 1986 Regents of the University of California. 323352Smckusick * All rights reserved. The Berkeley software License Agreement 423352Smckusick * specifies the terms and conditions for redistribution. 523352Smckusick * 6*36034Skarels * @(#)uba.c 7.6 (Berkeley) 10/22/88 723352Smckusick */ 840Sbill 917081Sbloom #include "param.h" 1017081Sbloom #include "systm.h" 1117081Sbloom #include "map.h" 1217081Sbloom #include "buf.h" 1317081Sbloom #include "vm.h" 1417081Sbloom #include "dir.h" 1517081Sbloom #include "user.h" 1617081Sbloom #include "proc.h" 1717081Sbloom #include "conf.h" 1830389Skarels #include "dkstat.h" 1917081Sbloom #include "kernel.h" 2040Sbill 21*36034Skarels #include "../vax/pte.h" 228481Sroot #include "../vax/cpu.h" 238481Sroot #include "../vax/mtpr.h" 248481Sroot #include "../vax/nexus.h" 2517081Sbloom #include "ubareg.h" 2617081Sbloom #include "ubavar.h" 278481Sroot 2829737Skarels #ifdef DW780 292929Swnj char ubasr_bits[] = UBASR_BITS; 302929Swnj #endif 312929Swnj 3226371Skarels #define spluba spl7 /* IPL 17 */ 3326371Skarels 3440Sbill /* 352570Swnj * Do transfer on device argument. The controller 362570Swnj * and uba involved are implied by the device. 372570Swnj * We queue for resource wait in the uba code if necessary. 382570Swnj * We return 1 if the transfer was started, 0 if it was not. 3932521Sbostic * 4032521Sbostic * The onq argument must be zero iff the device is not on the 4132521Sbostic * queue for this UBA. If onq is set, the device must be at the 4232521Sbostic * head of the queue. In any case, if the transfer is started, 4332521Sbostic * the device will be off the queue, and if not, it will be on. 4432521Sbostic * 4532521Sbostic * Drivers that allocate one BDP and hold it for some time should 4632521Sbostic * set ud_keepbdp. In this case um_bdp tells which BDP is allocated 4732521Sbostic * to the controller, unless it is zero, indicating that the controller 4832521Sbostic * does not now have a BDP. 492570Swnj */ 5032521Sbostic ubaqueue(ui, onq) 512958Swnj register struct uba_device *ui; 5232521Sbostic int onq; 532570Swnj { 542958Swnj register struct uba_ctlr *um = ui->ui_mi; 552570Swnj register struct uba_hd *uh; 5632521Sbostic register struct uba_driver *ud; 572570Swnj register int s, unit; 582570Swnj 592570Swnj uh = &uba_hd[um->um_ubanum]; 6032521Sbostic ud = um->um_driver; 6126371Skarels s = spluba(); 6232521Sbostic /* 6332521Sbostic * Honor exclusive BDP use requests. 6432521Sbostic */ 6532521Sbostic if (ud->ud_xclu && uh->uh_users > 0 || uh->uh_xclu) 662616Swnj goto rwait; 6732521Sbostic if (ud->ud_keepbdp) { 6832521Sbostic /* 6932521Sbostic * First get just a BDP (though in fact it comes with 7032521Sbostic * one map register too). 7132521Sbostic */ 7232521Sbostic if (um->um_bdp == 0) { 7332521Sbostic um->um_bdp = uballoc(um->um_ubanum, 7432521Sbostic (caddr_t)0, 0, UBA_NEEDBDP|UBA_CANTWAIT); 7532521Sbostic if (um->um_bdp == 0) 7632521Sbostic goto rwait; 7732521Sbostic } 7832521Sbostic /* now share it with this transfer */ 7932521Sbostic um->um_ubinfo = ubasetup(um->um_ubanum, 8032521Sbostic um->um_tab.b_actf->b_actf, 8132521Sbostic um->um_bdp|UBA_HAVEBDP|UBA_CANTWAIT); 8232521Sbostic } else 8332521Sbostic um->um_ubinfo = ubasetup(um->um_ubanum, 8432521Sbostic um->um_tab.b_actf->b_actf, UBA_NEEDBDP|UBA_CANTWAIT); 852616Swnj if (um->um_ubinfo == 0) 862616Swnj goto rwait; 872616Swnj uh->uh_users++; 8832521Sbostic if (ud->ud_xclu) 892616Swnj uh->uh_xclu = 1; 902570Swnj splx(s); 912570Swnj if (ui->ui_dk >= 0) { 922570Swnj unit = ui->ui_dk; 932570Swnj dk_busy |= 1<<unit; 946348Swnj dk_xfer[unit]++; 956348Swnj dk_wds[unit] += um->um_tab.b_actf->b_actf->b_bcount>>6; 962570Swnj } 9732521Sbostic if (onq) 982570Swnj uh->uh_actf = ui->ui_forw; 9932521Sbostic (*ud->ud_dgo)(um); 1002570Swnj return (1); 1012616Swnj rwait: 10232521Sbostic if (!onq) { 1032616Swnj ui->ui_forw = NULL; 1042616Swnj if (uh->uh_actf == NULL) 1052616Swnj uh->uh_actf = ui; 1062616Swnj else 1072616Swnj uh->uh_actl->ui_forw = ui; 1082616Swnj uh->uh_actl = ui; 1092616Swnj } 1102616Swnj splx(s); 1112616Swnj return (0); 1122570Swnj } 1132570Swnj 1142616Swnj ubadone(um) 1152958Swnj register struct uba_ctlr *um; 1162616Swnj { 1172616Swnj register struct uba_hd *uh = &uba_hd[um->um_ubanum]; 1182616Swnj 1192628Swnj if (um->um_driver->ud_xclu) 1202616Swnj uh->uh_xclu = 0; 1212616Swnj uh->uh_users--; 12232521Sbostic if (um->um_driver->ud_keepbdp) 12332521Sbostic um->um_ubinfo &= ~BDPMASK; /* keep BDP for misers */ 1242616Swnj ubarelse(um->um_ubanum, &um->um_ubinfo); 1252616Swnj } 1262616Swnj 1272570Swnj /* 1282395Swnj * Allocate and setup UBA map registers, and bdp's 1292395Swnj * Flags says whether bdp is needed, whether the caller can't 1302395Swnj * wait (e.g. if the caller is at interrupt level). 131*36034Skarels * Return value encodes map register plus page offset, 132*36034Skarels * bdp number and number of map registers. 13340Sbill */ 1342395Swnj ubasetup(uban, bp, flags) 13534284Skarels int uban; 13634284Skarels register struct buf *bp; 13734284Skarels register int flags; 13840Sbill { 1392395Swnj register struct uba_hd *uh = &uba_hd[uban]; 14034284Skarels register struct pte *pte, *io; 14134284Skarels register int npf; 14218417Smckusick int pfnum, temp; 14334284Skarels int reg, bdp; 14440Sbill unsigned v; 14540Sbill struct proc *rp; 14640Sbill int a, o, ubinfo; 14740Sbill 14829737Skarels #ifdef DW730 14929737Skarels if (uh->uh_type == DW730) 1503332Swnj flags &= ~UBA_NEEDBDP; 1513332Swnj #endif 15229737Skarels #ifdef QBA 15329737Skarels if (uh->uh_type == QBA) 15429737Skarels flags &= ~UBA_NEEDBDP; 15529737Skarels #endif 15640Sbill o = (int)bp->b_un.b_addr & PGOFSET; 15740Sbill npf = btoc(bp->b_bcount + o) + 1; 158*36034Skarels if (npf > UBA_MAXNMR) 159*36034Skarels panic("uba xfer too big"); 16026371Skarels a = spluba(); 1618811Sroot while ((reg = rmalloc(uh->uh_map, (long)npf)) == 0) { 1623913Swnj if (flags & UBA_CANTWAIT) { 1633913Swnj splx(a); 1642395Swnj return (0); 1653913Swnj } 1662395Swnj uh->uh_mrwant++; 1679353Ssam sleep((caddr_t)&uh->uh_mrwant, PSWP); 16840Sbill } 16917731Skarels if ((flags & UBA_NEED16) && reg + npf > 128) { 17017731Skarels /* 17117731Skarels * Could hang around and try again (if we can ever succeed). 17217731Skarels * Won't help any current device... 17317731Skarels */ 17417731Skarels rmfree(uh->uh_map, (long)npf, (long)reg); 17517731Skarels splx(a); 17617731Skarels return (0); 17717731Skarels } 17840Sbill bdp = 0; 1792395Swnj if (flags & UBA_NEEDBDP) { 18026371Skarels while ((bdp = ffs((long)uh->uh_bdpfree)) == 0) { 1812395Swnj if (flags & UBA_CANTWAIT) { 1828811Sroot rmfree(uh->uh_map, (long)npf, (long)reg); 1833913Swnj splx(a); 1842395Swnj return (0); 1852395Swnj } 1862395Swnj uh->uh_bdpwant++; 1879353Ssam sleep((caddr_t)&uh->uh_bdpwant, PSWP); 18840Sbill } 1892463Swnj uh->uh_bdpfree &= ~(1 << (bdp-1)); 1904758Swnj } else if (flags & UBA_HAVEBDP) 1914758Swnj bdp = (flags >> 28) & 0xf; 19240Sbill splx(a); 1932463Swnj reg--; 194*36034Skarels ubinfo = UBAI_INFO(o, reg, npf, bdp); 1952958Swnj temp = (bdp << 21) | UBAMR_MRV; 19640Sbill if (bdp && (o & 01)) 1972958Swnj temp |= UBAMR_BO; 1986382Swnj if ((bp->b_flags & B_PHYS) == 0) 19934284Skarels pte = kvtopte(bp->b_un.b_addr); 2006382Swnj else if (bp->b_flags & B_PAGET) 2016382Swnj pte = &Usrptmap[btokmx((struct pte *)bp->b_un.b_addr)]; 20234284Skarels else { 20334284Skarels rp = bp->b_flags&B_DIRTY ? &proc[2] : bp->b_proc; 20434284Skarels v = btop(bp->b_un.b_addr); 20534284Skarels if (bp->b_flags & B_UAREA) 20634284Skarels pte = &rp->p_addr[v]; 20734284Skarels else 20834284Skarels pte = vtopte(rp, v); 20934284Skarels } 21029737Skarels io = &uh->uh_mr[reg]; 21134284Skarels while (--npf > 0) { 21218417Smckusick pfnum = pte->pg_pfnum; 21318417Smckusick if (pfnum == 0) 2146382Swnj panic("uba zero uentry"); 21518417Smckusick pte++; 21618417Smckusick *(int *)io++ = pfnum | temp; 21740Sbill } 21834284Skarels *(int *)io = 0; 21940Sbill return (ubinfo); 22040Sbill } 22140Sbill 22240Sbill /* 2232570Swnj * Non buffer setup interface... set up a buffer and call ubasetup. 22440Sbill */ 2252395Swnj uballoc(uban, addr, bcnt, flags) 2263107Swnj int uban; 22740Sbill caddr_t addr; 2283107Swnj int bcnt, flags; 22940Sbill { 230883Sbill struct buf ubabuf; 23140Sbill 23240Sbill ubabuf.b_un.b_addr = addr; 23340Sbill ubabuf.b_flags = B_BUSY; 23440Sbill ubabuf.b_bcount = bcnt; 235883Sbill /* that's all the fields ubasetup() needs */ 2362395Swnj return (ubasetup(uban, &ubabuf, flags)); 23740Sbill } 23840Sbill 2392053Swnj /* 2402570Swnj * Release resources on uba uban, and then unblock resource waiters. 2412570Swnj * The map register parameter is by value since we need to block 2422570Swnj * against uba resets on 11/780's. 2432053Swnj */ 2442395Swnj ubarelse(uban, amr) 2452053Swnj int *amr; 24640Sbill { 2472395Swnj register struct uba_hd *uh = &uba_hd[uban]; 2482570Swnj register int bdp, reg, npf, s; 2492053Swnj int mr; 25040Sbill 2512570Swnj /* 2522570Swnj * Carefully see if we should release the space, since 2532570Swnj * it may be released asynchronously at uba reset time. 2542570Swnj */ 25526371Skarels s = spluba(); 2562053Swnj mr = *amr; 2572053Swnj if (mr == 0) { 2582570Swnj /* 2592570Swnj * A ubareset() occurred before we got around 2602570Swnj * to releasing the space... no need to bother. 2612570Swnj */ 2622570Swnj splx(s); 2632053Swnj return; 2642053Swnj } 2652067Swnj *amr = 0; 266*36034Skarels bdp = UBAI_BDP(mr); 26740Sbill if (bdp) { 26829737Skarels switch (uh->uh_type) { 26934284Skarels #ifdef DWBUA 27034284Skarels case DWBUA: 27134284Skarels BUA(uh->uh_uba)->bua_dpr[bdp] |= BUADPR_PURGE; 27234284Skarels break; 27334284Skarels #endif 27429737Skarels #ifdef DW780 27529737Skarels case DW780: 2762958Swnj uh->uh_uba->uba_dpr[bdp] |= UBADPR_BNE; 2772423Skre break; 2782423Skre #endif 27929737Skarels #ifdef DW750 28029737Skarels case DW750: 2812958Swnj uh->uh_uba->uba_dpr[bdp] |= 2822958Swnj UBADPR_PURGE|UBADPR_NXM|UBADPR_UCE; 2832423Skre break; 2842423Skre #endif 28529737Skarels default: 28629737Skarels break; 2872423Skre } 2882570Swnj uh->uh_bdpfree |= 1 << (bdp-1); /* atomic */ 2892395Swnj if (uh->uh_bdpwant) { 2902395Swnj uh->uh_bdpwant = 0; 2919353Ssam wakeup((caddr_t)&uh->uh_bdpwant); 29240Sbill } 29340Sbill } 2942570Swnj /* 2952570Swnj * Put back the registers in the resource map. 29617731Skarels * The map code must not be reentered, 29717731Skarels * nor can the registers be freed twice. 29817731Skarels * Unblock interrupts once this is done. 2992570Swnj */ 300*36034Skarels npf = UBAI_NMR(mr); 301*36034Skarels reg = UBAI_MR(mr) + 1; 3028811Sroot rmfree(uh->uh_map, (long)npf, (long)reg); 3032570Swnj splx(s); 3042570Swnj 3052570Swnj /* 3062570Swnj * Wakeup sleepers for map registers, 3072570Swnj * and also, if there are processes blocked in dgo(), 3082570Swnj * give them a chance at the UNIBUS. 3092570Swnj */ 3102395Swnj if (uh->uh_mrwant) { 3112395Swnj uh->uh_mrwant = 0; 3129353Ssam wakeup((caddr_t)&uh->uh_mrwant); 31340Sbill } 31432521Sbostic while (uh->uh_actf && ubaqueue(uh->uh_actf, 1)) 3152570Swnj ; 31640Sbill } 31740Sbill 3182729Swnj ubapurge(um) 3192958Swnj register struct uba_ctlr *um; 3202729Swnj { 3212729Swnj register struct uba_hd *uh = um->um_hd; 322*36034Skarels register int bdp = UBAI_BDP(um->um_ubinfo); 3232729Swnj 32429737Skarels switch (uh->uh_type) { 32534284Skarels #ifdef DWBUA 32634284Skarels case DWBUA: 32734284Skarels BUA(uh->uh_uba)->bua_dpr[bdp] |= BUADPR_PURGE; 32834284Skarels break; 32934284Skarels #endif 33029737Skarels #ifdef DW780 33129737Skarels case DW780: 3322958Swnj uh->uh_uba->uba_dpr[bdp] |= UBADPR_BNE; 3332729Swnj break; 3342729Swnj #endif 33529737Skarels #ifdef DW750 33629737Skarels case DW750: 3372958Swnj uh->uh_uba->uba_dpr[bdp] |= UBADPR_PURGE|UBADPR_NXM|UBADPR_UCE; 3382729Swnj break; 3392729Swnj #endif 34029737Skarels default: 34129737Skarels break; 3422729Swnj } 3432729Swnj } 3442729Swnj 3456863Swnj ubainitmaps(uhp) 3466863Swnj register struct uba_hd *uhp; 3476863Swnj { 3486863Swnj 349*36034Skarels if (uhp->uh_memsize > UBA_MAXMR) 350*36034Skarels uhp->uh_memsize = UBA_MAXMR; 35129737Skarels rminit(uhp->uh_map, (long)uhp->uh_memsize, (long)1, "uba", UAMSIZ); 35229737Skarels switch (uhp->uh_type) { 35334284Skarels #ifdef DWBUA 35434284Skarels case DWBUA: 35534284Skarels uhp->uh_bdpfree = (1<<NBDPBUA) - 1; 35634284Skarels break; 35734284Skarels #endif 35829737Skarels #ifdef DW780 35929737Skarels case DW780: 3606863Swnj uhp->uh_bdpfree = (1<<NBDP780) - 1; 3616863Swnj break; 3626863Swnj #endif 36329737Skarels #ifdef DW750 36429737Skarels case DW750: 3656863Swnj uhp->uh_bdpfree = (1<<NBDP750) - 1; 3666863Swnj break; 3676863Swnj #endif 36829737Skarels default: 3696863Swnj break; 3706863Swnj } 3716863Swnj } 3726863Swnj 3732570Swnj /* 3742570Swnj * Generate a reset on uba number uban. Then 3752570Swnj * call each device in the character device table, 3762570Swnj * giving it a chance to clean up so as to be able to continue. 3772570Swnj */ 3782395Swnj ubareset(uban) 3792570Swnj int uban; 380284Sbill { 381284Sbill register struct cdevsw *cdp; 3822646Swnj register struct uba_hd *uh = &uba_hd[uban]; 3831781Sbill int s; 384284Sbill 38526371Skarels s = spluba(); 3862646Swnj uh->uh_users = 0; 3872646Swnj uh->uh_zvcnt = 0; 3882646Swnj uh->uh_xclu = 0; 3892646Swnj uh->uh_actf = uh->uh_actl = 0; 3902646Swnj uh->uh_bdpwant = 0; 3912646Swnj uh->uh_mrwant = 0; 3926863Swnj ubainitmaps(uh); 3932646Swnj wakeup((caddr_t)&uh->uh_bdpwant); 3942646Swnj wakeup((caddr_t)&uh->uh_mrwant); 3952958Swnj printf("uba%d: reset", uban); 3962958Swnj ubainit(uh->uh_uba); 39717731Skarels ubameminit(uban); 39811722Ssam for (cdp = cdevsw; cdp < cdevsw + nchrdev; cdp++) 3992395Swnj (*cdp->d_reset)(uban); 4005221Swnj ifubareset(uban); 401284Sbill printf("\n"); 402302Sbill splx(s); 403284Sbill } 4042395Swnj 4052570Swnj /* 4062570Swnj * Init a uba. This is called with a pointer 4072570Swnj * rather than a virtual address since it is called 4082570Swnj * by code which runs with memory mapping disabled. 4092570Swnj * In these cases we really don't need the interrupts 4102570Swnj * enabled, but since we run with ipl high, we don't care 4112570Swnj * if they are, they will never happen anyways. 41229737Skarels * SHOULD GET POINTER TO UBA_HD INSTEAD OF UBA. 4132570Swnj */ 4142423Skre ubainit(uba) 4152423Skre register struct uba_regs *uba; 4162395Swnj { 41729737Skarels register struct uba_hd *uhp; 41834284Skarels #ifdef QBA 41929737Skarels int isphys = 0; 42034284Skarels #endif 4212395Swnj 42229737Skarels for (uhp = uba_hd; uhp < uba_hd + numuba; uhp++) { 42329737Skarels if (uhp->uh_uba == uba) 42429737Skarels break; 42529737Skarels if (uhp->uh_physuba == uba) { 42634284Skarels #ifdef QBA 42729737Skarels isphys++; 42834284Skarels #endif 42929737Skarels break; 43029737Skarels } 43129737Skarels } 43229737Skarels if (uhp >= uba_hd + numuba) { 43329737Skarels printf("init unknown uba\n"); 43429737Skarels return; 43529737Skarels } 43629737Skarels 43729737Skarels switch (uhp->uh_type) { 43834284Skarels #ifdef DWBUA 43934284Skarels case DWBUA: 44034284Skarels BUA(uba)->bua_csr |= BUACSR_UPI; 44134284Skarels /* give devices time to recover from power fail */ 44234284Skarels DELAY(500000); 44334284Skarels break; 44434284Skarels #endif 44529737Skarels #ifdef DW780 44629737Skarels case DW780: 4472958Swnj uba->uba_cr = UBACR_ADINIT; 4482958Swnj uba->uba_cr = UBACR_IFS|UBACR_BRIE|UBACR_USEFIE|UBACR_SUEFIE; 4492958Swnj while ((uba->uba_cnfgr & UBACNFGR_UBIC) == 0) 4502958Swnj ; 4512958Swnj break; 4522958Swnj #endif 45329737Skarels #ifdef DW750 45429737Skarels case DW750: 4553352Swnj #endif 45629737Skarels #ifdef DW730 45729737Skarels case DW730: 4583352Swnj #endif 45929737Skarels #ifdef QBA 46029737Skarels case QBA: 46127255Skridle #endif 46229737Skarels #if DW750 || DW730 || QBA 4633352Swnj mtpr(IUR, 0); 4642958Swnj /* give devices time to recover from power fail */ 4653332Swnj /* THIS IS PROBABLY UNNECESSARY */ 4663352Swnj DELAY(500000); 4673332Swnj /* END PROBABLY UNNECESSARY */ 46829737Skarels #ifdef QBA 46929737Skarels /* 47029737Skarels * Re-enable local memory access 47129737Skarels * from the Q-bus. 47229737Skarels */ 47329737Skarels if (uhp->uh_type == QBA) { 47429737Skarels if (isphys) 47529737Skarels *((char *)QIOPAGE630 + QIPCR) = Q_LMEAE; 47629737Skarels else 47729737Skarels *(uhp->uh_iopage + QIPCR) = Q_LMEAE; 47829737Skarels } 47929737Skarels #endif QBA 4802958Swnj break; 48129737Skarels #endif DW750 || DW730 || QBA 4822958Swnj } 4832395Swnj } 4842395Swnj 485*36034Skarels #ifdef QBA 486*36034Skarels /* 487*36034Skarels * Determine the interrupt priority of a Q-bus 488*36034Skarels * peripheral. The device probe routine must spl6(), 489*36034Skarels * attempt to make the device request an interrupt, 490*36034Skarels * delaying as necessary, then call this routine 491*36034Skarels * before resetting the device. 492*36034Skarels */ 493*36034Skarels qbgetpri() 494*36034Skarels { 495*36034Skarels int pri; 496*36034Skarels extern int cvec; 497*36034Skarels 498*36034Skarels for (pri = 0x17; pri > 0x14; ) { 499*36034Skarels if (cvec && cvec != 0x200) /* interrupted at pri */ 500*36034Skarels break; 501*36034Skarels pri--; 502*36034Skarels splx(pri - 1); 503*36034Skarels } 504*36034Skarels (void) spl0(); 505*36034Skarels return (pri); 506*36034Skarels } 507*36034Skarels #endif 508*36034Skarels 50929737Skarels #ifdef DW780 5104024Swnj int ubawedgecnt = 10; 5114024Swnj int ubacrazy = 500; 51217731Skarels int zvcnt_max = 5000; /* in 8 sec */ 5132570Swnj /* 51424500Sbloom * This routine is called by the locore code to process a UBA 51524500Sbloom * error on an 11/780 or 8600. The arguments are passed 5162570Swnj * on the stack, and value-result (through some trickery). 5172570Swnj * In particular, the uvec argument is used for further 5182570Swnj * uba processing so the result aspect of it is very important. 5192570Swnj * It must not be declared register. 5202570Swnj */ 5212423Skre /*ARGSUSED*/ 52217731Skarels ubaerror(uban, uh, ipl, uvec, uba) 5232395Swnj register int uban; 5242395Swnj register struct uba_hd *uh; 52517731Skarels int ipl, uvec; 5262395Swnj register struct uba_regs *uba; 5272395Swnj { 5282395Swnj register sr, s; 5292395Swnj 5302395Swnj if (uvec == 0) { 53126215Skarels /* 53226215Skarels * Declare dt as unsigned so that negative values 53326215Skarels * are handled as >8 below, in case time was set back. 53426215Skarels */ 53526215Skarels u_long dt = time.tv_sec - uh->uh_zvtime; 53626215Skarels 53726215Skarels uh->uh_zvtotal++; 53817731Skarels if (dt > 8) { 53926215Skarels uh->uh_zvtime = time.tv_sec; 54017731Skarels uh->uh_zvcnt = 0; 54117731Skarels } 54217731Skarels if (++uh->uh_zvcnt > zvcnt_max) { 54317731Skarels printf("uba%d: too many zero vectors (%d in <%d sec)\n", 54417731Skarels uban, uh->uh_zvcnt, dt + 1); 54517731Skarels printf("\tIPL 0x%x\n\tcnfgr: %b Adapter Code: 0x%x\n", 54617731Skarels ipl, uba->uba_cnfgr&(~0xff), UBACNFGR_BITS, 54717731Skarels uba->uba_cnfgr&0xff); 54817731Skarels printf("\tsr: %b\n\tdcr: %x (MIC %sOK)\n", 54917731Skarels uba->uba_sr, ubasr_bits, uba->uba_dcr, 55017731Skarels (uba->uba_dcr&0x8000000)?"":"NOT "); 5512395Swnj ubareset(uban); 5522395Swnj } 5532395Swnj return; 5542395Swnj } 5552395Swnj if (uba->uba_cnfgr & NEX_CFGFLT) { 5562929Swnj printf("uba%d: sbi fault sr=%b cnfgr=%b\n", 5572929Swnj uban, uba->uba_sr, ubasr_bits, 5583248Swnj uba->uba_cnfgr, NEXFLT_BITS); 5592395Swnj ubareset(uban); 5602395Swnj uvec = 0; 5612395Swnj return; 5622395Swnj } 5632395Swnj sr = uba->uba_sr; 56426371Skarels s = spluba(); 5653473Swnj printf("uba%d: uba error sr=%b fmer=%x fubar=%o\n", 5663473Swnj uban, uba->uba_sr, ubasr_bits, uba->uba_fmer, 4*uba->uba_fubar); 5672395Swnj splx(s); 5682395Swnj uba->uba_sr = sr; 5692958Swnj uvec &= UBABRRVR_DIV; 5704024Swnj if (++uh->uh_errcnt % ubawedgecnt == 0) { 5714024Swnj if (uh->uh_errcnt > ubacrazy) 5724024Swnj panic("uba crazy"); 5734024Swnj printf("ERROR LIMIT "); 5744024Swnj ubareset(uban); 5754024Swnj uvec = 0; 5764024Swnj return; 5774024Swnj } 5782395Swnj return; 5792395Swnj } 5802395Swnj #endif 5813745Sroot 5823745Sroot /* 58317731Skarels * Look for devices with unibus memory, allow them to configure, then disable 58417731Skarels * map registers as necessary. Called during autoconfiguration and ubareset. 58517731Skarels * The device ubamem routine returns 0 on success, 1 on success if it is fully 58617731Skarels * configured (has no csr or interrupt, so doesn't need to be probed), 58717731Skarels * and -1 on failure. 58817731Skarels */ 58917731Skarels ubameminit(uban) 59017731Skarels { 59117731Skarels register struct uba_device *ui; 59217731Skarels register struct uba_hd *uh = &uba_hd[uban]; 59317731Skarels caddr_t umembase = umem[uban] + 0x3e000, addr; 59417731Skarels #define ubaoff(off) ((int)(off) & 0x1fff) 59517731Skarels 59617731Skarels uh->uh_lastmem = 0; 59717731Skarels for (ui = ubdinit; ui->ui_driver; ui++) { 59817731Skarels if (ui->ui_ubanum != uban && ui->ui_ubanum != '?') 59917731Skarels continue; 60017731Skarels if (ui->ui_driver->ud_ubamem) { 60117731Skarels /* 60217731Skarels * During autoconfiguration, need to fudge ui_addr. 60317731Skarels */ 60417731Skarels addr = ui->ui_addr; 60517731Skarels ui->ui_addr = umembase + ubaoff(addr); 60617731Skarels switch ((*ui->ui_driver->ud_ubamem)(ui, uban)) { 60717731Skarels case 1: 60817731Skarels ui->ui_alive = 1; 60917731Skarels /* FALLTHROUGH */ 61017731Skarels case 0: 61117731Skarels ui->ui_ubanum = uban; 61217731Skarels break; 61317731Skarels } 61417731Skarels ui->ui_addr = addr; 61517731Skarels } 61617731Skarels } 61729737Skarels #ifdef DW780 61817731Skarels /* 61929737Skarels * On a DW780, throw away any map registers disabled by rounding 62017731Skarels * the map disable in the configuration register 62117731Skarels * up to the next 8K boundary, or below the last unibus memory. 62217731Skarels */ 62329737Skarels if (uh->uh_type == DW780) { 62417731Skarels register i; 62517731Skarels 62617731Skarels i = btop(((uh->uh_lastmem + 8191) / 8192) * 8192); 62717731Skarels while (i) 62817731Skarels (void) rmget(uh->uh_map, 1, i--); 62917731Skarels } 63017731Skarels #endif 63117731Skarels } 63217731Skarels 63317731Skarels /* 63414790Ssam * Allocate UNIBUS memory. Allocates and initializes 63514790Ssam * sufficient mapping registers for access. On a 780, 63614790Ssam * the configuration register is setup to disable UBA 63714790Ssam * response on DMA transfers to addresses controlled 63814790Ssam * by the disabled mapping registers. 63929737Skarels * On a DW780, should only be called from ubameminit, or in ascending order 64017731Skarels * from 0 with 8K-sized and -aligned addresses; freeing memory that isn't 64117731Skarels * the last unibus memory would free unusable map registers. 64217731Skarels * Doalloc is 1 to allocate, 0 to deallocate. 6436518Sfeldman */ 64414790Ssam ubamem(uban, addr, npg, doalloc) 64514790Ssam int uban, addr, npg, doalloc; 6466518Sfeldman { 6476518Sfeldman register struct uba_hd *uh = &uba_hd[uban]; 64814790Ssam register int a; 64917731Skarels int s; 6506518Sfeldman 65117731Skarels a = (addr >> 9) + 1; 65226371Skarels s = spluba(); 65317731Skarels if (doalloc) 65417731Skarels a = rmget(uh->uh_map, npg, a); 65517731Skarels else 65617731Skarels rmfree(uh->uh_map, (long)npg, (long)a); 65717731Skarels splx(s); 6586518Sfeldman if (a) { 65914790Ssam register int i, *m; 66014790Ssam 66129737Skarels m = (int *)&uh->uh_mr[a - 1]; 66214790Ssam for (i = 0; i < npg; i++) 6636518Sfeldman *m++ = 0; /* All off, especially 'valid' */ 66417731Skarels i = addr + npg * 512; 66517731Skarels if (doalloc && i > uh->uh_lastmem) 66617731Skarels uh->uh_lastmem = i; 66717731Skarels else if (doalloc == 0 && i == uh->uh_lastmem) 66817731Skarels uh->uh_lastmem = addr; 66929737Skarels #ifdef DW780 67014790Ssam /* 67114790Ssam * On a 780, set up the map register disable 67214790Ssam * field in the configuration register. Beware 67317731Skarels * of callers that request memory ``out of order'' 67417731Skarels * or in sections other than 8K multiples. 67517731Skarels * Ubameminit handles such requests properly, however. 67614790Ssam */ 67729737Skarels if (uh->uh_type == DW780) { 67817731Skarels i = uh->uh_uba->uba_cr &~ 0x7c000000; 67917731Skarels i |= ((uh->uh_lastmem + 8191) / 8192) << 26; 68017731Skarels uh->uh_uba->uba_cr = i; 6817473Sfeldman } 6827473Sfeldman #endif 6836518Sfeldman } 68414790Ssam return (a); 6856518Sfeldman } 6867304Ssam 6879875Ssam #include "ik.h" 68824501Sjg #include "vs.h" 68924501Sjg #if NIK > 0 || NVS > 0 6907304Ssam /* 6917304Ssam * Map a virtual address into users address space. Actually all we 6927304Ssam * do is turn on the user mode write protection bits for the particular 6937304Ssam * page of memory involved. 6947304Ssam */ 6957304Ssam maptouser(vaddress) 6967304Ssam caddr_t vaddress; 6977304Ssam { 6987304Ssam 69934284Skarels kvtopte(vaddress)->pg_prot = (PG_UW >> 27); 7007304Ssam } 7017304Ssam 7027304Ssam unmaptouser(vaddress) 7037304Ssam caddr_t vaddress; 7047304Ssam { 7057304Ssam 70634284Skarels kvtopte(vaddress)->pg_prot = (PG_KW >> 27); 7077304Ssam } 7089174Ssam #endif 709