1 /* uba.c 4.7 02/10/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 uh->uh_uba->uba_dpr[bdp] |= UBA_BNE; 131 uh->uh_bdpfree |= 1 << bdp; 132 if (uh->uh_bdpwant) { 133 uh->uh_bdpwant = 0; 134 wakeup((caddr_t)uh->uh_map); 135 } 136 } 137 npf = (mr >> 18) & 0x3ff; 138 reg = ((mr >> 9) & 0x1ff) + 1; 139 mfree(uh->uh_map, npf, reg); 140 if (uh->uh_mrwant) { 141 uh->uh_mrwant = 0; 142 wakeup((caddr_t)uh->uh_map); 143 } 144 splx(a); 145 } 146 147 #define DELAY(N) { register int d; d = N; while (--d > 0); } 148 149 ubareset(uban) 150 { 151 struct uba_regs *up; 152 register struct cdevsw *cdp; 153 int s; 154 155 s = spl6(); 156 switch (cpu) { 157 #if VAX==780 158 case VAX_780: 159 printf("UBA RESET %d:", uban); 160 ubainit(uba_hd[uban].uh_uba); 161 break; 162 #endif 163 #if VAX==750 164 case VAX_750: 165 printf("UNIBUS INIT:"); 166 mtpr(IUR, 1); 167 DELAY(100000); 168 break; 169 #endif 170 } 171 for (cdp = cdevsw; cdp->d_open; cdp++) 172 (*cdp->d_reset)(uban); 173 printf("\n"); 174 splx(s); 175 } 176 177 /* pointer rather than number so we can be called with virt and phys addrs */ 178 ubainit(up) 179 register struct uba_regs *up; 180 { 181 182 up->uba_cr = UBA_ADINIT; 183 up->uba_cr = UBA_IFS|UBA_BRIE|UBA_USEFIE|UBA_SUEFIE; 184 while ((up->uba_cnfgr & UBA_UBIC) == 0) 185 ; 186 } 187 188 #if VAX780 189 unhang() 190 { 191 register int uban; 192 193 for (uban = 0; uban < numuba; uban++) { 194 register struct uba_hd *uh = &uba_hd[uban]; 195 register struct uba_regs *up = uh->uh_uba; 196 197 if (up->uba_sr == 0) 198 return; 199 uh->uh_hangcnt++; 200 if (uh->uh_hangcnt > 5*HZ) { 201 uh->uh_hangcnt = 0; 202 printf("HANG "); 203 ubareset(uban); 204 } 205 } 206 } 207 208 /* timeout routine to decrement ``i forgot to interrupt counts */ 209 /* this prevents the counts from growing slowly, which isn't interesting */ 210 ubawatch() 211 { 212 register struct uba_hd *uh; 213 register int uban; 214 215 for (uban = 0; uban < numuba; uban++) { 216 uh = &uba_hd[uban]; 217 if (uh->uh_hangcnt) 218 uh->uh_hangcnt--; 219 } 220 } 221 222 /* called from locore.s; parameters here (i.e. uvec) are value-result! */ 223 ubaerror(uban, uh, xx, uvec, uba) 224 register int uban; 225 register struct uba_hd *uh; 226 int uvec; 227 register struct uba_regs *uba; 228 { 229 register sr, s; 230 231 if (uvec == 0) { 232 uh->uh_zvcnt++; 233 if (uh->uh_zvcnt > 250000) { 234 printf("ZERO VECTOR "); 235 ubareset(uban); 236 } 237 uvec = 0; 238 return; 239 } 240 if (uba->uba_cnfgr & NEX_CFGFLT) { 241 printf("UBA%d SBI FAULT sr %x cnfgr %x\n", 242 uban, uba->uba_sr, uba->uba_cnfgr); 243 ubareset(uban); 244 uvec = 0; 245 return; 246 } 247 sr = uba->uba_sr; 248 s = spl7(); 249 printf("UBA%d ERROR SR %x FMER %x FUBAR %o\n", 250 uba->uba_sr, uba->uba_fmer, uba->uba_fubar); 251 splx(s); 252 uba->uba_sr = sr; 253 uvec &= UBA_DIV; 254 return; 255 } 256 #endif 257