1 /* uba.c 4.8 02/15/81 */ 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/uba.h" 10 #include "../h/dir.h" 11 #include "../h/user.h" 12 #include "../h/proc.h" 13 #include "../h/vm.h" 14 #include "../h/conf.h" 15 #include "../h/mtpr.h" 16 #include "../h/nexus.h" 17 18 /* 19 * Allocate and setup UBA map registers, and bdp's 20 * Flags says whether bdp is needed, whether the caller can't 21 * wait (e.g. if the caller is at interrupt level). 22 * 23 * Return value (cruft): 24 * Bits 0-8 Byte offset 25 * Bits 9-17 Start map reg. no. 26 * Bits 18-27 No. mapping reg's 27 * Bits 28-31 BDP no. 28 */ 29 ubasetup(uban, bp, flags) 30 struct buf *bp; 31 { 32 register struct uba_hd *uh = &uba_hd[uban]; 33 register int temp, i; 34 int npf, reg, bdp; 35 unsigned v; 36 register struct pte *pte, *io; 37 struct proc *rp; 38 int a, o, ubinfo; 39 40 v = btop(bp->b_un.b_addr); 41 o = (int)bp->b_un.b_addr & PGOFSET; 42 npf = btoc(bp->b_bcount + o) + 1; 43 a = spl6(); 44 while ((reg = malloc(uh->uh_map, npf)) == 0) { 45 if (flags & UBA_CANTWAIT) 46 return (0); 47 uh->uh_mrwant++; 48 sleep((caddr_t)uh->uh_map, PSWP); 49 } 50 reg--; 51 bdp = 0; 52 if (flags & UBA_NEEDBDP) { 53 while ((bdp = ffs(uh->uh_bdpfree)) == 0) { 54 if (flags & UBA_CANTWAIT) { 55 mfree(uh->uh_map, npf, reg); 56 return (0); 57 } 58 uh->uh_bdpwant++; 59 sleep((caddr_t)uh->uh_map, PSWP); 60 } 61 uh->uh_bdpfree &= ~ (1<<bdp); 62 } 63 splx(a); 64 ubinfo = (bdp << 28) | (npf << 18) | (reg << 9) | o; 65 io = &uh->uh_uba->uba_map[reg]; 66 temp = (bdp << 21) | UBA_MRV; 67 rp = bp->b_flags&B_DIRTY ? &proc[2] : bp->b_proc; 68 if (bdp && (o & 01)) 69 temp |= UBA_BO; 70 if (bp->b_flags & B_UAREA) { 71 for (i = UPAGES - bp->b_bcount / NBPG; i < UPAGES; i++) { 72 if (rp->p_addr[i].pg_pfnum == 0) 73 panic("uba: zero upage"); 74 *(int *)io++ = rp->p_addr[i].pg_pfnum | temp; 75 } 76 } else if ((bp->b_flags & B_PHYS) == 0) { 77 pte = &Sysmap[btop(((int)bp->b_un.b_addr)&0x7fffffff)]; 78 while (--npf != 0) 79 *(int *)io++ = pte++->pg_pfnum | temp; 80 } else { 81 if (bp->b_flags & B_PAGET) 82 pte = &Usrptmap[btokmx((struct pte *)bp->b_un.b_addr)]; 83 else 84 pte = vtopte(rp, v); 85 while (--npf != 0) { 86 if (pte->pg_pfnum == 0) 87 panic("uba zero uentry"); 88 *(int *)io++ = pte++->pg_pfnum | temp; 89 } 90 } 91 *(int *)io++ = 0; 92 return (ubinfo); 93 } 94 95 /* 96 * Non buffer unibus interface... set up a buffer and call ubasetup. 97 */ 98 uballoc(uban, addr, bcnt, flags) 99 caddr_t addr; 100 unsigned short bcnt; 101 { 102 struct buf ubabuf; 103 104 ubabuf.b_un.b_addr = addr; 105 ubabuf.b_flags = B_BUSY; 106 ubabuf.b_bcount = bcnt; 107 /* that's all the fields ubasetup() needs */ 108 return (ubasetup(uban, &ubabuf, flags)); 109 } 110 111 /* 112 * Old ubafree(info) is now ubarelse(&info) to avoid races. 113 */ 114 ubarelse(uban, amr) 115 int *amr; 116 { 117 register struct uba_hd *uh = &uba_hd[uban]; 118 register int bdp, reg, npf, a; 119 int mr; 120 121 a = spl6(); 122 mr = *amr; 123 if (mr == 0) { 124 splx(a); 125 return; 126 } 127 *amr = 0; 128 bdp = (mr >> 28) & 0x0f; 129 if (bdp) { 130 switch (cpu) 131 { 132 #if VAX780 133 case VAX_780: 134 uh->uh_uba->uba_dpr[bdp] |= UBA_BNE; 135 break; 136 #endif 137 #if VAX750 138 case VAX_750: 139 uh->uh_uba->uba_dpr[bdp] |= UBA_PURGE|UBA_NXM|UBA_UCE; 140 break; 141 #endif 142 } 143 uh->uh_bdpfree |= 1 << bdp; 144 if (uh->uh_bdpwant) { 145 uh->uh_bdpwant = 0; 146 wakeup((caddr_t)uh->uh_map); 147 } 148 } 149 npf = (mr >> 18) & 0x3ff; 150 reg = ((mr >> 9) & 0x1ff) + 1; 151 mfree(uh->uh_map, npf, reg); 152 if (uh->uh_mrwant) { 153 uh->uh_mrwant = 0; 154 wakeup((caddr_t)uh->uh_map); 155 } 156 splx(a); 157 } 158 159 #define DELAY(N) { register int d; d = N; while (--d > 0); } 160 161 ubareset(uban) 162 { 163 register struct cdevsw *cdp; 164 int s; 165 166 s = spl6(); 167 switch (cpu) { 168 #if VAX==780 169 case VAX_780: 170 printf("UBA RESET %d:", uban); 171 ubainit(uba_hd[uban].uh_uba); 172 break; 173 #endif 174 #if VAX==750 175 case VAX_750: 176 printf("UNIBUS INIT:"); 177 mtpr(IUR, 1); 178 DELAY(100000); 179 break; 180 #endif 181 } 182 for (cdp = cdevsw; cdp->d_open; cdp++) 183 (*cdp->d_reset)(uban); 184 printf("\n"); 185 splx(s); 186 } 187 188 /* pointer rather than number so we can be called with virt and phys addrs */ 189 ubainit(uba) 190 register struct uba_regs *uba; 191 { 192 193 uba->uba_cr = UBA_ADINIT; 194 uba->uba_cr = UBA_IFS|UBA_BRIE|UBA_USEFIE|UBA_SUEFIE; 195 while ((uba->uba_cnfgr & UBA_UBIC) == 0) 196 ; 197 } 198 199 #if VAX780 200 unhang() 201 { 202 register int uban; 203 204 for (uban = 0; uban < numuba; uban++) { 205 register struct uba_hd *uh = &uba_hd[uban]; 206 register struct uba_regs *up = uh->uh_uba; 207 208 if (up->uba_sr == 0) 209 return; 210 uh->uh_hangcnt++; 211 if (uh->uh_hangcnt > 5*HZ) { 212 uh->uh_hangcnt = 0; 213 printf("HANG "); 214 ubareset(uban); 215 } 216 } 217 } 218 219 /* timeout routine to decrement ``i forgot to interrupt counts */ 220 /* this prevents the counts from growing slowly, which isn't interesting */ 221 ubawatch() 222 { 223 register struct uba_hd *uh; 224 register int uban; 225 226 for (uban = 0; uban < numuba; uban++) { 227 uh = &uba_hd[uban]; 228 if (uh->uh_hangcnt) 229 uh->uh_hangcnt--; 230 } 231 } 232 233 /* called from locore.s; parameters here (i.e. uvec) are value-result! */ 234 /*ARGSUSED*/ 235 ubaerror(uban, uh, xx, uvec, uba) 236 register int uban; 237 register struct uba_hd *uh; 238 int uvec; 239 register struct uba_regs *uba; 240 { 241 register sr, s; 242 243 if (uvec == 0) { 244 uh->uh_zvcnt++; 245 if (uh->uh_zvcnt > 250000) { 246 printf("ZERO VECTOR "); 247 ubareset(uban); 248 } 249 uvec = 0; 250 return; 251 } 252 if (uba->uba_cnfgr & NEX_CFGFLT) { 253 printf("UBA%d SBI FAULT sr %x cnfgr %x\n", 254 uban, uba->uba_sr, uba->uba_cnfgr); 255 ubareset(uban); 256 uvec = 0; 257 return; 258 } 259 sr = uba->uba_sr; 260 s = spl7(); 261 printf("UBA%d ERROR SR %x FMER %x FUBAR %o\n", 262 uban, uba->uba_sr, uba->uba_fmer, uba->uba_fubar); 263 splx(s); 264 uba->uba_sr = sr; 265 uvec &= UBA_DIV; 266 return; 267 } 268 #endif 269