1*2423Skre /* uba.c 4.8 02/15/81 */ 240Sbill 340Sbill #include "../h/param.h" 42395Swnj #include "../h/systm.h" 52395Swnj #include "../h/cpu.h" 640Sbill #include "../h/map.h" 740Sbill #include "../h/pte.h" 82395Swnj #include "../h/buf.h" 940Sbill #include "../h/uba.h" 1040Sbill #include "../h/dir.h" 1140Sbill #include "../h/user.h" 1240Sbill #include "../h/proc.h" 1340Sbill #include "../h/vm.h" 14284Sbill #include "../h/conf.h" 151901Swnj #include "../h/mtpr.h" 162395Swnj #include "../h/nexus.h" 1740Sbill 1840Sbill /* 192395Swnj * Allocate and setup UBA map registers, and bdp's 202395Swnj * Flags says whether bdp is needed, whether the caller can't 212395Swnj * wait (e.g. if the caller is at interrupt level). 2240Sbill * 232395Swnj * Return value (cruft): 2440Sbill * Bits 0-8 Byte offset 2540Sbill * Bits 9-17 Start map reg. no. 2640Sbill * Bits 18-27 No. mapping reg's 2740Sbill * Bits 28-31 BDP no. 2840Sbill */ 292395Swnj ubasetup(uban, bp, flags) 302395Swnj struct buf *bp; 3140Sbill { 322395Swnj register struct uba_hd *uh = &uba_hd[uban]; 3340Sbill register int temp, i; 3440Sbill int npf, reg, bdp; 3540Sbill unsigned v; 3640Sbill register struct pte *pte, *io; 3740Sbill struct proc *rp; 3840Sbill int a, o, ubinfo; 3940Sbill 4040Sbill v = btop(bp->b_un.b_addr); 4140Sbill o = (int)bp->b_un.b_addr & PGOFSET; 4240Sbill npf = btoc(bp->b_bcount + o) + 1; 4340Sbill a = spl6(); 442395Swnj while ((reg = malloc(uh->uh_map, npf)) == 0) { 452395Swnj if (flags & UBA_CANTWAIT) 462395Swnj return (0); 472395Swnj uh->uh_mrwant++; 482395Swnj sleep((caddr_t)uh->uh_map, PSWP); 4940Sbill } 5040Sbill reg--; 5140Sbill bdp = 0; 522395Swnj if (flags & UBA_NEEDBDP) { 532395Swnj while ((bdp = ffs(uh->uh_bdpfree)) == 0) { 542395Swnj if (flags & UBA_CANTWAIT) { 552395Swnj mfree(uh->uh_map, npf, reg); 562395Swnj return (0); 572395Swnj } 582395Swnj uh->uh_bdpwant++; 592395Swnj sleep((caddr_t)uh->uh_map, PSWP); 6040Sbill } 612395Swnj uh->uh_bdpfree &= ~ (1<<bdp); 622395Swnj } 6340Sbill splx(a); 6440Sbill ubinfo = (bdp << 28) | (npf << 18) | (reg << 9) | o; 652395Swnj io = &uh->uh_uba->uba_map[reg]; 662395Swnj temp = (bdp << 21) | UBA_MRV; 6740Sbill rp = bp->b_flags&B_DIRTY ? &proc[2] : bp->b_proc; 6840Sbill if (bdp && (o & 01)) 692395Swnj temp |= UBA_BO; 7040Sbill if (bp->b_flags & B_UAREA) { 7140Sbill for (i = UPAGES - bp->b_bcount / NBPG; i < UPAGES; i++) { 7240Sbill if (rp->p_addr[i].pg_pfnum == 0) 7340Sbill panic("uba: zero upage"); 7440Sbill *(int *)io++ = rp->p_addr[i].pg_pfnum | temp; 7540Sbill } 7640Sbill } else if ((bp->b_flags & B_PHYS) == 0) { 77728Sbill pte = &Sysmap[btop(((int)bp->b_un.b_addr)&0x7fffffff)]; 7840Sbill while (--npf != 0) 79728Sbill *(int *)io++ = pte++->pg_pfnum | temp; 8040Sbill } else { 8140Sbill if (bp->b_flags & B_PAGET) 8240Sbill pte = &Usrptmap[btokmx((struct pte *)bp->b_un.b_addr)]; 8340Sbill else 8440Sbill pte = vtopte(rp, v); 8540Sbill while (--npf != 0) { 8640Sbill if (pte->pg_pfnum == 0) 8740Sbill panic("uba zero uentry"); 8840Sbill *(int *)io++ = pte++->pg_pfnum | temp; 8940Sbill } 9040Sbill } 9140Sbill *(int *)io++ = 0; 9240Sbill return (ubinfo); 9340Sbill } 9440Sbill 9540Sbill /* 9640Sbill * Non buffer unibus interface... set up a buffer and call ubasetup. 9740Sbill */ 982395Swnj uballoc(uban, addr, bcnt, flags) 9940Sbill caddr_t addr; 10040Sbill unsigned short bcnt; 10140Sbill { 102883Sbill struct buf ubabuf; 10340Sbill 10440Sbill ubabuf.b_un.b_addr = addr; 10540Sbill ubabuf.b_flags = B_BUSY; 10640Sbill ubabuf.b_bcount = bcnt; 107883Sbill /* that's all the fields ubasetup() needs */ 1082395Swnj return (ubasetup(uban, &ubabuf, flags)); 10940Sbill } 11040Sbill 1112053Swnj /* 1122053Swnj * Old ubafree(info) is now ubarelse(&info) to avoid races. 1132053Swnj */ 1142395Swnj ubarelse(uban, amr) 1152053Swnj int *amr; 11640Sbill { 1172395Swnj register struct uba_hd *uh = &uba_hd[uban]; 11840Sbill register int bdp, reg, npf, a; 1192053Swnj int mr; 12040Sbill 12140Sbill a = spl6(); 1222053Swnj mr = *amr; 1232053Swnj if (mr == 0) { 1242053Swnj splx(a); 1252053Swnj return; 1262053Swnj } 1272067Swnj *amr = 0; 12840Sbill bdp = (mr >> 28) & 0x0f; 12940Sbill if (bdp) { 130*2423Skre switch (cpu) 131*2423Skre { 132*2423Skre #if VAX780 133*2423Skre case VAX_780: 134*2423Skre uh->uh_uba->uba_dpr[bdp] |= UBA_BNE; 135*2423Skre break; 136*2423Skre #endif 137*2423Skre #if VAX750 138*2423Skre case VAX_750: 139*2423Skre uh->uh_uba->uba_dpr[bdp] |= UBA_PURGE|UBA_NXM|UBA_UCE; 140*2423Skre break; 141*2423Skre #endif 142*2423Skre } 1432395Swnj uh->uh_bdpfree |= 1 << bdp; 1442395Swnj if (uh->uh_bdpwant) { 1452395Swnj uh->uh_bdpwant = 0; 1462395Swnj wakeup((caddr_t)uh->uh_map); 14740Sbill } 14840Sbill } 14940Sbill npf = (mr >> 18) & 0x3ff; 15040Sbill reg = ((mr >> 9) & 0x1ff) + 1; 1512395Swnj mfree(uh->uh_map, npf, reg); 1522395Swnj if (uh->uh_mrwant) { 1532395Swnj uh->uh_mrwant = 0; 1542395Swnj wakeup((caddr_t)uh->uh_map); 15540Sbill } 15640Sbill splx(a); 15740Sbill } 15840Sbill 159284Sbill #define DELAY(N) { register int d; d = N; while (--d > 0); } 160284Sbill 1612395Swnj ubareset(uban) 162284Sbill { 163284Sbill register struct cdevsw *cdp; 1641781Sbill int s; 165284Sbill 166302Sbill s = spl6(); 1672395Swnj switch (cpu) { 1681901Swnj #if VAX==780 1692395Swnj case VAX_780: 1702395Swnj printf("UBA RESET %d:", uban); 1712395Swnj ubainit(uba_hd[uban].uh_uba); 1722395Swnj break; 1731901Swnj #endif 1741901Swnj #if VAX==750 1752395Swnj case VAX_750: 1762395Swnj printf("UNIBUS INIT:"); 1772395Swnj mtpr(IUR, 1); 1782395Swnj DELAY(100000); 1792395Swnj break; 1801901Swnj #endif 1812395Swnj } 182284Sbill for (cdp = cdevsw; cdp->d_open; cdp++) 1832395Swnj (*cdp->d_reset)(uban); 184284Sbill printf("\n"); 185302Sbill splx(s); 186284Sbill } 1872395Swnj 1882395Swnj /* pointer rather than number so we can be called with virt and phys addrs */ 189*2423Skre ubainit(uba) 190*2423Skre register struct uba_regs *uba; 1912395Swnj { 1922395Swnj 193*2423Skre uba->uba_cr = UBA_ADINIT; 194*2423Skre uba->uba_cr = UBA_IFS|UBA_BRIE|UBA_USEFIE|UBA_SUEFIE; 195*2423Skre while ((uba->uba_cnfgr & UBA_UBIC) == 0) 1962395Swnj ; 1972395Swnj } 1982395Swnj 1992395Swnj #if VAX780 2002395Swnj unhang() 2012395Swnj { 2022395Swnj register int uban; 2032395Swnj 2042395Swnj for (uban = 0; uban < numuba; uban++) { 2052395Swnj register struct uba_hd *uh = &uba_hd[uban]; 2062395Swnj register struct uba_regs *up = uh->uh_uba; 2072395Swnj 2082395Swnj if (up->uba_sr == 0) 2092395Swnj return; 2102395Swnj uh->uh_hangcnt++; 2112395Swnj if (uh->uh_hangcnt > 5*HZ) { 2122395Swnj uh->uh_hangcnt = 0; 2132395Swnj printf("HANG "); 2142395Swnj ubareset(uban); 2152395Swnj } 2162395Swnj } 2172395Swnj } 2182395Swnj 2192395Swnj /* timeout routine to decrement ``i forgot to interrupt counts */ 2202395Swnj /* this prevents the counts from growing slowly, which isn't interesting */ 2212395Swnj ubawatch() 2222395Swnj { 2232395Swnj register struct uba_hd *uh; 2242395Swnj register int uban; 2252395Swnj 2262395Swnj for (uban = 0; uban < numuba; uban++) { 2272395Swnj uh = &uba_hd[uban]; 2282395Swnj if (uh->uh_hangcnt) 2292395Swnj uh->uh_hangcnt--; 2302395Swnj } 2312395Swnj } 2322395Swnj 2332395Swnj /* called from locore.s; parameters here (i.e. uvec) are value-result! */ 234*2423Skre /*ARGSUSED*/ 2352395Swnj ubaerror(uban, uh, xx, uvec, uba) 2362395Swnj register int uban; 2372395Swnj register struct uba_hd *uh; 2382395Swnj int uvec; 2392395Swnj register struct uba_regs *uba; 2402395Swnj { 2412395Swnj register sr, s; 2422395Swnj 2432395Swnj if (uvec == 0) { 2442395Swnj uh->uh_zvcnt++; 2452395Swnj if (uh->uh_zvcnt > 250000) { 2462395Swnj printf("ZERO VECTOR "); 2472395Swnj ubareset(uban); 2482395Swnj } 2492395Swnj uvec = 0; 2502395Swnj return; 2512395Swnj } 2522395Swnj if (uba->uba_cnfgr & NEX_CFGFLT) { 2532395Swnj printf("UBA%d SBI FAULT sr %x cnfgr %x\n", 2542395Swnj uban, uba->uba_sr, uba->uba_cnfgr); 2552395Swnj ubareset(uban); 2562395Swnj uvec = 0; 2572395Swnj return; 2582395Swnj } 2592395Swnj sr = uba->uba_sr; 2602395Swnj s = spl7(); 2612395Swnj printf("UBA%d ERROR SR %x FMER %x FUBAR %o\n", 262*2423Skre uban, uba->uba_sr, uba->uba_fmer, uba->uba_fubar); 2632395Swnj splx(s); 2642395Swnj uba->uba_sr = sr; 2652395Swnj uvec &= UBA_DIV; 2662395Swnj return; 2672395Swnj } 2682395Swnj #endif 269