1*2570Swnj /* uba.c 4.11 02/19/81 */ 240Sbill 3*2570Swnj #define DELAY(N) { register int d; d = N; while (--d > 0); } 4*2570Swnj 540Sbill #include "../h/param.h" 62395Swnj #include "../h/systm.h" 72395Swnj #include "../h/cpu.h" 840Sbill #include "../h/map.h" 940Sbill #include "../h/pte.h" 102395Swnj #include "../h/buf.h" 11*2570Swnj #include "../h/vm.h" 1240Sbill #include "../h/uba.h" 1340Sbill #include "../h/dir.h" 1440Sbill #include "../h/user.h" 1540Sbill #include "../h/proc.h" 16284Sbill #include "../h/conf.h" 171901Swnj #include "../h/mtpr.h" 182395Swnj #include "../h/nexus.h" 19*2570Swnj #include "../h/dk.h" 2040Sbill 2140Sbill /* 22*2570Swnj * Do transfer on device argument. The controller 23*2570Swnj * and uba involved are implied by the device. 24*2570Swnj * We queue for resource wait in the uba code if necessary. 25*2570Swnj * We return 1 if the transfer was started, 0 if it was not. 26*2570Swnj * If you call this routine with the head of the queue for a 27*2570Swnj * UBA, it will automatically remove the device from the UBA 28*2570Swnj * queue before it returns. If some other device is given 29*2570Swnj * as argument, it will be added to the request queue if the 30*2570Swnj * request cannot be started immediately. This means that 31*2570Swnj * passing a device which is on the queue but not at the head 32*2570Swnj * of the request queue is likely to be a disaster. 33*2570Swnj */ 34*2570Swnj ubago(ui) 35*2570Swnj register struct uba_dinfo *ui; 36*2570Swnj { 37*2570Swnj register struct uba_minfo *um = ui->ui_mi; 38*2570Swnj register struct uba_hd *uh; 39*2570Swnj register int s, unit; 40*2570Swnj 41*2570Swnj uh = &uba_hd[um->um_ubanum]; 42*2570Swnj s = spl6(); 43*2570Swnj um->um_ubinfo = ubasetup(um->um_ubanum, um->um_tab.b_actf->b_actf, 44*2570Swnj UBA_NEEDBDP|UBA_CANTWAIT); 45*2570Swnj if (um->um_ubinfo == 0) { 46*2570Swnj if (uh->uh_actf != ui) { 47*2570Swnj ui->ui_forw = NULL; 48*2570Swnj if (uh->uh_actf == NULL) 49*2570Swnj uh->uh_actf = ui; 50*2570Swnj else 51*2570Swnj uh->uh_actl->ui_forw = ui; 52*2570Swnj uh->uh_actl = ui; 53*2570Swnj } 54*2570Swnj splx(s); 55*2570Swnj return (0); 56*2570Swnj } 57*2570Swnj splx(s); 58*2570Swnj if (ui->ui_dk >= 0) { 59*2570Swnj unit = ui->ui_dk; 60*2570Swnj dk_busy |= 1<<unit; 61*2570Swnj } 62*2570Swnj if (uh->uh_actf == ui) 63*2570Swnj uh->uh_actf = ui->ui_forw; 64*2570Swnj (*um->um_driver->ud_dgo)(um); 65*2570Swnj if (ui->ui_dk >= 0) { 66*2570Swnj dk_xfer[unit]++; 67*2570Swnj dk_wds[unit] += um->um_tab.b_actf->b_bcount>>6; 68*2570Swnj } 69*2570Swnj return (1); 70*2570Swnj } 71*2570Swnj 72*2570Swnj /* 732395Swnj * Allocate and setup UBA map registers, and bdp's 742395Swnj * Flags says whether bdp is needed, whether the caller can't 752395Swnj * wait (e.g. if the caller is at interrupt level). 7640Sbill * 77*2570Swnj * Return value: 7840Sbill * Bits 0-8 Byte offset 7940Sbill * Bits 9-17 Start map reg. no. 8040Sbill * Bits 18-27 No. mapping reg's 8140Sbill * Bits 28-31 BDP no. 8240Sbill */ 832395Swnj ubasetup(uban, bp, flags) 842395Swnj struct buf *bp; 8540Sbill { 862395Swnj register struct uba_hd *uh = &uba_hd[uban]; 8740Sbill register int temp, i; 8840Sbill int npf, reg, bdp; 8940Sbill unsigned v; 9040Sbill register struct pte *pte, *io; 9140Sbill struct proc *rp; 9240Sbill int a, o, ubinfo; 9340Sbill 9440Sbill v = btop(bp->b_un.b_addr); 9540Sbill o = (int)bp->b_un.b_addr & PGOFSET; 9640Sbill npf = btoc(bp->b_bcount + o) + 1; 9740Sbill a = spl6(); 982395Swnj while ((reg = malloc(uh->uh_map, npf)) == 0) { 992395Swnj if (flags & UBA_CANTWAIT) 1002395Swnj return (0); 1012395Swnj uh->uh_mrwant++; 1022395Swnj sleep((caddr_t)uh->uh_map, PSWP); 10340Sbill } 10440Sbill bdp = 0; 1052395Swnj if (flags & UBA_NEEDBDP) { 1062395Swnj while ((bdp = ffs(uh->uh_bdpfree)) == 0) { 1072395Swnj if (flags & UBA_CANTWAIT) { 1082395Swnj mfree(uh->uh_map, npf, reg); 1092395Swnj return (0); 1102395Swnj } 1112395Swnj uh->uh_bdpwant++; 1122395Swnj sleep((caddr_t)uh->uh_map, PSWP); 11340Sbill } 1142463Swnj uh->uh_bdpfree &= ~(1 << (bdp-1)); 1152395Swnj } 11640Sbill splx(a); 1172463Swnj reg--; 11840Sbill ubinfo = (bdp << 28) | (npf << 18) | (reg << 9) | o; 1192395Swnj io = &uh->uh_uba->uba_map[reg]; 1202395Swnj temp = (bdp << 21) | UBA_MRV; 12140Sbill rp = bp->b_flags&B_DIRTY ? &proc[2] : bp->b_proc; 12240Sbill if (bdp && (o & 01)) 1232395Swnj temp |= UBA_BO; 12440Sbill if (bp->b_flags & B_UAREA) { 12540Sbill for (i = UPAGES - bp->b_bcount / NBPG; i < UPAGES; i++) { 12640Sbill if (rp->p_addr[i].pg_pfnum == 0) 12740Sbill panic("uba: zero upage"); 12840Sbill *(int *)io++ = rp->p_addr[i].pg_pfnum | temp; 12940Sbill } 13040Sbill } else if ((bp->b_flags & B_PHYS) == 0) { 131728Sbill pte = &Sysmap[btop(((int)bp->b_un.b_addr)&0x7fffffff)]; 13240Sbill while (--npf != 0) 133728Sbill *(int *)io++ = pte++->pg_pfnum | temp; 13440Sbill } else { 13540Sbill if (bp->b_flags & B_PAGET) 13640Sbill pte = &Usrptmap[btokmx((struct pte *)bp->b_un.b_addr)]; 13740Sbill else 13840Sbill pte = vtopte(rp, v); 13940Sbill while (--npf != 0) { 14040Sbill if (pte->pg_pfnum == 0) 14140Sbill panic("uba zero uentry"); 14240Sbill *(int *)io++ = pte++->pg_pfnum | temp; 14340Sbill } 14440Sbill } 14540Sbill *(int *)io++ = 0; 14640Sbill return (ubinfo); 14740Sbill } 14840Sbill 14940Sbill /* 150*2570Swnj * Non buffer setup interface... set up a buffer and call ubasetup. 15140Sbill */ 1522395Swnj uballoc(uban, addr, bcnt, flags) 15340Sbill caddr_t addr; 15440Sbill unsigned short bcnt; 15540Sbill { 156883Sbill struct buf ubabuf; 15740Sbill 15840Sbill ubabuf.b_un.b_addr = addr; 15940Sbill ubabuf.b_flags = B_BUSY; 16040Sbill ubabuf.b_bcount = bcnt; 161883Sbill /* that's all the fields ubasetup() needs */ 1622395Swnj return (ubasetup(uban, &ubabuf, flags)); 16340Sbill } 16440Sbill 1652053Swnj /* 166*2570Swnj * Release resources on uba uban, and then unblock resource waiters. 167*2570Swnj * The map register parameter is by value since we need to block 168*2570Swnj * against uba resets on 11/780's. 1692053Swnj */ 1702395Swnj ubarelse(uban, amr) 1712053Swnj int *amr; 17240Sbill { 1732395Swnj register struct uba_hd *uh = &uba_hd[uban]; 174*2570Swnj register int bdp, reg, npf, s; 1752053Swnj int mr; 17640Sbill 177*2570Swnj /* 178*2570Swnj * Carefully see if we should release the space, since 179*2570Swnj * it may be released asynchronously at uba reset time. 180*2570Swnj */ 181*2570Swnj s = spl6(); 1822053Swnj mr = *amr; 1832053Swnj if (mr == 0) { 184*2570Swnj /* 185*2570Swnj * A ubareset() occurred before we got around 186*2570Swnj * to releasing the space... no need to bother. 187*2570Swnj */ 188*2570Swnj splx(s); 1892053Swnj return; 1902053Swnj } 1912067Swnj *amr = 0; 192*2570Swnj splx(s); /* let interrupts in, we're safe for a while */ 19340Sbill bdp = (mr >> 28) & 0x0f; 19440Sbill if (bdp) { 1952423Skre switch (cpu) 1962423Skre { 1972423Skre #if VAX780 1982423Skre case VAX_780: 1992423Skre uh->uh_uba->uba_dpr[bdp] |= UBA_BNE; 2002423Skre break; 2012423Skre #endif 2022423Skre #if VAX750 2032423Skre case VAX_750: 2042423Skre uh->uh_uba->uba_dpr[bdp] |= UBA_PURGE|UBA_NXM|UBA_UCE; 2052423Skre break; 2062423Skre #endif 2072423Skre } 208*2570Swnj uh->uh_bdpfree |= 1 << (bdp-1); /* atomic */ 2092395Swnj if (uh->uh_bdpwant) { 2102395Swnj uh->uh_bdpwant = 0; 2112395Swnj wakeup((caddr_t)uh->uh_map); 21240Sbill } 21340Sbill } 214*2570Swnj /* 215*2570Swnj * Put back the registers in the resource map. 216*2570Swnj * The map code must not be reentered, so we do this 217*2570Swnj * at high ipl. 218*2570Swnj */ 21940Sbill npf = (mr >> 18) & 0x3ff; 22040Sbill reg = ((mr >> 9) & 0x1ff) + 1; 221*2570Swnj s = spl6(); 2222395Swnj mfree(uh->uh_map, npf, reg); 223*2570Swnj splx(s); 224*2570Swnj 225*2570Swnj /* 226*2570Swnj * Wakeup sleepers for map registers, 227*2570Swnj * and also, if there are processes blocked in dgo(), 228*2570Swnj * give them a chance at the UNIBUS. 229*2570Swnj */ 2302395Swnj if (uh->uh_mrwant) { 2312395Swnj uh->uh_mrwant = 0; 2322395Swnj wakeup((caddr_t)uh->uh_map); 23340Sbill } 234*2570Swnj while (uh->uh_actf && ubago(uh->uh_actf)) 235*2570Swnj ; 23640Sbill } 23740Sbill 238*2570Swnj /* 239*2570Swnj * Generate a reset on uba number uban. Then 240*2570Swnj * call each device in the character device table, 241*2570Swnj * giving it a chance to clean up so as to be able to continue. 242*2570Swnj */ 2432395Swnj ubareset(uban) 244*2570Swnj int uban; 245284Sbill { 246284Sbill register struct cdevsw *cdp; 2471781Sbill int s; 248284Sbill 249302Sbill s = spl6(); 2502395Swnj switch (cpu) { 2511901Swnj #if VAX==780 2522395Swnj case VAX_780: 2532395Swnj printf("UBA RESET %d:", uban); 2542395Swnj ubainit(uba_hd[uban].uh_uba); 2552395Swnj break; 2561901Swnj #endif 2571901Swnj #if VAX==750 2582395Swnj case VAX_750: 2592395Swnj printf("UNIBUS INIT:"); 2602395Swnj mtpr(IUR, 1); 2612395Swnj DELAY(100000); 2622395Swnj break; 2631901Swnj #endif 2642395Swnj } 265284Sbill for (cdp = cdevsw; cdp->d_open; cdp++) 2662395Swnj (*cdp->d_reset)(uban); 267284Sbill printf("\n"); 268302Sbill splx(s); 269284Sbill } 2702395Swnj 271*2570Swnj /* 272*2570Swnj * Init a uba. This is called with a pointer 273*2570Swnj * rather than a virtual address since it is called 274*2570Swnj * by code which runs with memory mapping disabled. 275*2570Swnj * In these cases we really don't need the interrupts 276*2570Swnj * enabled, but since we run with ipl high, we don't care 277*2570Swnj * if they are, they will never happen anyways. 278*2570Swnj */ 2792423Skre ubainit(uba) 2802423Skre register struct uba_regs *uba; 2812395Swnj { 2822395Swnj 2832423Skre uba->uba_cr = UBA_ADINIT; 2842423Skre uba->uba_cr = UBA_IFS|UBA_BRIE|UBA_USEFIE|UBA_SUEFIE; 2852423Skre while ((uba->uba_cnfgr & UBA_UBIC) == 0) 2862395Swnj ; 2872395Swnj } 2882395Swnj 2892395Swnj #if VAX780 290*2570Swnj /* 291*2570Swnj * Check to make sure the UNIBUS adaptor is not hung, 292*2570Swnj * with an interrupt in the register to be presented, 293*2570Swnj * but not presenting it for an extended period (5 seconds). 294*2570Swnj */ 2952395Swnj unhang() 2962395Swnj { 2972395Swnj register int uban; 2982395Swnj 2992395Swnj for (uban = 0; uban < numuba; uban++) { 3002395Swnj register struct uba_hd *uh = &uba_hd[uban]; 3012395Swnj register struct uba_regs *up = uh->uh_uba; 3022395Swnj 3032395Swnj if (up->uba_sr == 0) 3042395Swnj return; 3052395Swnj uh->uh_hangcnt++; 3062395Swnj if (uh->uh_hangcnt > 5*HZ) { 3072395Swnj uh->uh_hangcnt = 0; 3082395Swnj printf("HANG "); 3092395Swnj ubareset(uban); 3102395Swnj } 3112395Swnj } 3122395Swnj } 3132395Swnj 314*2570Swnj /* 315*2570Swnj * This is a timeout routine which decrements the ``i forgot to 316*2570Swnj * interrupt'' counts, on an 11/780. This prevents slowly growing 317*2570Swnj * counts from causing a UBA reset since we are interested only 318*2570Swnj * in hang situations. 319*2570Swnj */ 3202395Swnj ubawatch() 3212395Swnj { 3222395Swnj register struct uba_hd *uh; 3232395Swnj register int uban; 3242395Swnj 3252395Swnj for (uban = 0; uban < numuba; uban++) { 3262395Swnj uh = &uba_hd[uban]; 3272395Swnj if (uh->uh_hangcnt) 3282395Swnj uh->uh_hangcnt--; 3292395Swnj } 3302395Swnj } 3312395Swnj 332*2570Swnj /* 333*2570Swnj * This routine is called by the locore code to 334*2570Swnj * process a UBA error on an 11/780. The arguments are passed 335*2570Swnj * on the stack, and value-result (through some trickery). 336*2570Swnj * In particular, the uvec argument is used for further 337*2570Swnj * uba processing so the result aspect of it is very important. 338*2570Swnj * It must not be declared register. 339*2570Swnj */ 3402423Skre /*ARGSUSED*/ 3412395Swnj ubaerror(uban, uh, xx, uvec, uba) 3422395Swnj register int uban; 3432395Swnj register struct uba_hd *uh; 3442395Swnj int uvec; 3452395Swnj register struct uba_regs *uba; 3462395Swnj { 3472395Swnj register sr, s; 3482395Swnj 3492395Swnj if (uvec == 0) { 3502395Swnj uh->uh_zvcnt++; 3512395Swnj if (uh->uh_zvcnt > 250000) { 3522395Swnj printf("ZERO VECTOR "); 3532395Swnj ubareset(uban); 3542395Swnj } 3552395Swnj uvec = 0; 3562395Swnj return; 3572395Swnj } 3582395Swnj if (uba->uba_cnfgr & NEX_CFGFLT) { 3592395Swnj printf("UBA%d SBI FAULT sr %x cnfgr %x\n", 3602395Swnj uban, uba->uba_sr, uba->uba_cnfgr); 3612395Swnj ubareset(uban); 3622395Swnj uvec = 0; 3632395Swnj return; 3642395Swnj } 3652395Swnj sr = uba->uba_sr; 3662395Swnj s = spl7(); 3672395Swnj printf("UBA%d ERROR SR %x FMER %x FUBAR %o\n", 3682470Swnj uban, uba->uba_sr, uba->uba_fmer, 4*uba->uba_fubar); 3692395Swnj splx(s); 3702395Swnj uba->uba_sr = sr; 3712395Swnj uvec &= UBA_DIV; 3722395Swnj return; 3732395Swnj } 3742395Swnj #endif 375