1*2958Swnj /* uba.c 4.20 03/06/81 */ 240Sbill 32570Swnj #define DELAY(N) { register int d; d = N; while (--d > 0); } 42570Swnj 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" 112570Swnj #include "../h/vm.h" 12*2958Swnj #include "../h/ubareg.h" 13*2958Swnj #include "../h/ubavar.h" 1440Sbill #include "../h/dir.h" 1540Sbill #include "../h/user.h" 1640Sbill #include "../h/proc.h" 17284Sbill #include "../h/conf.h" 181901Swnj #include "../h/mtpr.h" 192395Swnj #include "../h/nexus.h" 202570Swnj #include "../h/dk.h" 2140Sbill 222929Swnj #if VAX780 232929Swnj char ubasr_bits[] = UBASR_BITS; 242929Swnj #endif 252929Swnj 2640Sbill /* 272570Swnj * Do transfer on device argument. The controller 282570Swnj * and uba involved are implied by the device. 292570Swnj * We queue for resource wait in the uba code if necessary. 302570Swnj * We return 1 if the transfer was started, 0 if it was not. 312570Swnj * If you call this routine with the head of the queue for a 322570Swnj * UBA, it will automatically remove the device from the UBA 332570Swnj * queue before it returns. If some other device is given 342570Swnj * as argument, it will be added to the request queue if the 352570Swnj * request cannot be started immediately. This means that 362570Swnj * passing a device which is on the queue but not at the head 372570Swnj * of the request queue is likely to be a disaster. 382570Swnj */ 392570Swnj ubago(ui) 40*2958Swnj register struct uba_device *ui; 412570Swnj { 42*2958Swnj register struct uba_ctlr *um = ui->ui_mi; 432570Swnj register struct uba_hd *uh; 442570Swnj register int s, unit; 452570Swnj 462570Swnj uh = &uba_hd[um->um_ubanum]; 472570Swnj s = spl6(); 482628Swnj if (um->um_driver->ud_xclu && uh->uh_users > 0 || uh->uh_xclu) 492616Swnj goto rwait; 502570Swnj um->um_ubinfo = ubasetup(um->um_ubanum, um->um_tab.b_actf->b_actf, 512570Swnj UBA_NEEDBDP|UBA_CANTWAIT); 522616Swnj if (um->um_ubinfo == 0) 532616Swnj goto rwait; 542616Swnj uh->uh_users++; 552628Swnj if (um->um_driver->ud_xclu) 562616Swnj uh->uh_xclu = 1; 572570Swnj splx(s); 582570Swnj if (ui->ui_dk >= 0) { 592570Swnj unit = ui->ui_dk; 602570Swnj dk_busy |= 1<<unit; 612570Swnj } 622570Swnj if (uh->uh_actf == ui) 632570Swnj uh->uh_actf = ui->ui_forw; 642570Swnj (*um->um_driver->ud_dgo)(um); 652570Swnj if (ui->ui_dk >= 0) { 662570Swnj dk_xfer[unit]++; 672570Swnj dk_wds[unit] += um->um_tab.b_actf->b_bcount>>6; 682570Swnj } 692570Swnj return (1); 702616Swnj rwait: 712616Swnj if (uh->uh_actf != ui) { 722616Swnj ui->ui_forw = NULL; 732616Swnj if (uh->uh_actf == NULL) 742616Swnj uh->uh_actf = ui; 752616Swnj else 762616Swnj uh->uh_actl->ui_forw = ui; 772616Swnj uh->uh_actl = ui; 782616Swnj } 792616Swnj splx(s); 802616Swnj return (0); 812570Swnj } 822570Swnj 832616Swnj ubadone(um) 84*2958Swnj register struct uba_ctlr *um; 852616Swnj { 862616Swnj register struct uba_hd *uh = &uba_hd[um->um_ubanum]; 872616Swnj 882628Swnj if (um->um_driver->ud_xclu) 892616Swnj uh->uh_xclu = 0; 902616Swnj uh->uh_users--; 912616Swnj ubarelse(um->um_ubanum, &um->um_ubinfo); 922616Swnj } 932616Swnj 942570Swnj /* 952395Swnj * Allocate and setup UBA map registers, and bdp's 962395Swnj * Flags says whether bdp is needed, whether the caller can't 972395Swnj * wait (e.g. if the caller is at interrupt level). 9840Sbill * 992570Swnj * Return value: 10040Sbill * Bits 0-8 Byte offset 10140Sbill * Bits 9-17 Start map reg. no. 10240Sbill * Bits 18-27 No. mapping reg's 10340Sbill * Bits 28-31 BDP no. 10440Sbill */ 1052395Swnj ubasetup(uban, bp, flags) 1062395Swnj struct buf *bp; 10740Sbill { 1082395Swnj register struct uba_hd *uh = &uba_hd[uban]; 10940Sbill register int temp, i; 11040Sbill int npf, reg, bdp; 11140Sbill unsigned v; 11240Sbill register struct pte *pte, *io; 11340Sbill struct proc *rp; 11440Sbill int a, o, ubinfo; 11540Sbill 11640Sbill v = btop(bp->b_un.b_addr); 11740Sbill o = (int)bp->b_un.b_addr & PGOFSET; 11840Sbill npf = btoc(bp->b_bcount + o) + 1; 11940Sbill a = spl6(); 1202784Swnj while ((reg = rmalloc(uh->uh_map, npf)) == 0) { 1212395Swnj if (flags & UBA_CANTWAIT) 1222395Swnj return (0); 1232395Swnj uh->uh_mrwant++; 1242395Swnj sleep((caddr_t)uh->uh_map, PSWP); 12540Sbill } 12640Sbill bdp = 0; 1272395Swnj if (flags & UBA_NEEDBDP) { 1282395Swnj while ((bdp = ffs(uh->uh_bdpfree)) == 0) { 1292395Swnj if (flags & UBA_CANTWAIT) { 1302784Swnj rmfree(uh->uh_map, npf, reg); 1312395Swnj return (0); 1322395Swnj } 1332395Swnj uh->uh_bdpwant++; 1342395Swnj sleep((caddr_t)uh->uh_map, PSWP); 13540Sbill } 1362463Swnj uh->uh_bdpfree &= ~(1 << (bdp-1)); 1372395Swnj } 13840Sbill splx(a); 1392463Swnj reg--; 14040Sbill ubinfo = (bdp << 28) | (npf << 18) | (reg << 9) | o; 1412395Swnj io = &uh->uh_uba->uba_map[reg]; 142*2958Swnj temp = (bdp << 21) | UBAMR_MRV; 14340Sbill rp = bp->b_flags&B_DIRTY ? &proc[2] : bp->b_proc; 14440Sbill if (bdp && (o & 01)) 145*2958Swnj temp |= UBAMR_BO; 14640Sbill if (bp->b_flags & B_UAREA) { 14740Sbill for (i = UPAGES - bp->b_bcount / NBPG; i < UPAGES; i++) { 14840Sbill if (rp->p_addr[i].pg_pfnum == 0) 14940Sbill panic("uba: zero upage"); 15040Sbill *(int *)io++ = rp->p_addr[i].pg_pfnum | temp; 15140Sbill } 15240Sbill } else if ((bp->b_flags & B_PHYS) == 0) { 153728Sbill pte = &Sysmap[btop(((int)bp->b_un.b_addr)&0x7fffffff)]; 15440Sbill while (--npf != 0) 155728Sbill *(int *)io++ = pte++->pg_pfnum | temp; 15640Sbill } else { 15740Sbill if (bp->b_flags & B_PAGET) 15840Sbill pte = &Usrptmap[btokmx((struct pte *)bp->b_un.b_addr)]; 15940Sbill else 16040Sbill pte = vtopte(rp, v); 16140Sbill while (--npf != 0) { 16240Sbill if (pte->pg_pfnum == 0) 16340Sbill panic("uba zero uentry"); 16440Sbill *(int *)io++ = pte++->pg_pfnum | temp; 16540Sbill } 16640Sbill } 16740Sbill *(int *)io++ = 0; 16840Sbill return (ubinfo); 16940Sbill } 17040Sbill 17140Sbill /* 1722570Swnj * Non buffer setup interface... set up a buffer and call ubasetup. 17340Sbill */ 1742395Swnj uballoc(uban, addr, bcnt, flags) 17540Sbill caddr_t addr; 17640Sbill unsigned short bcnt; 17740Sbill { 178883Sbill struct buf ubabuf; 17940Sbill 18040Sbill ubabuf.b_un.b_addr = addr; 18140Sbill ubabuf.b_flags = B_BUSY; 18240Sbill ubabuf.b_bcount = bcnt; 183883Sbill /* that's all the fields ubasetup() needs */ 1842395Swnj return (ubasetup(uban, &ubabuf, flags)); 18540Sbill } 18640Sbill 1872053Swnj /* 1882570Swnj * Release resources on uba uban, and then unblock resource waiters. 1892570Swnj * The map register parameter is by value since we need to block 1902570Swnj * against uba resets on 11/780's. 1912053Swnj */ 1922395Swnj ubarelse(uban, amr) 1932053Swnj int *amr; 19440Sbill { 1952395Swnj register struct uba_hd *uh = &uba_hd[uban]; 1962570Swnj register int bdp, reg, npf, s; 1972053Swnj int mr; 19840Sbill 1992570Swnj /* 2002570Swnj * Carefully see if we should release the space, since 2012570Swnj * it may be released asynchronously at uba reset time. 2022570Swnj */ 2032570Swnj s = spl6(); 2042053Swnj mr = *amr; 2052053Swnj if (mr == 0) { 2062570Swnj /* 2072570Swnj * A ubareset() occurred before we got around 2082570Swnj * to releasing the space... no need to bother. 2092570Swnj */ 2102570Swnj splx(s); 2112053Swnj return; 2122053Swnj } 2132067Swnj *amr = 0; 2142570Swnj splx(s); /* let interrupts in, we're safe for a while */ 21540Sbill bdp = (mr >> 28) & 0x0f; 21640Sbill if (bdp) { 2172729Swnj switch (cpu) { 2182423Skre #if VAX780 2192423Skre case VAX_780: 220*2958Swnj uh->uh_uba->uba_dpr[bdp] |= UBADPR_BNE; 2212423Skre break; 2222423Skre #endif 2232423Skre #if VAX750 2242423Skre case VAX_750: 225*2958Swnj uh->uh_uba->uba_dpr[bdp] |= 226*2958Swnj UBADPR_PURGE|UBADPR_NXM|UBADPR_UCE; 2272423Skre break; 2282423Skre #endif 2292423Skre } 2302570Swnj uh->uh_bdpfree |= 1 << (bdp-1); /* atomic */ 2312395Swnj if (uh->uh_bdpwant) { 2322395Swnj uh->uh_bdpwant = 0; 2332395Swnj wakeup((caddr_t)uh->uh_map); 23440Sbill } 23540Sbill } 2362570Swnj /* 2372570Swnj * Put back the registers in the resource map. 2382570Swnj * The map code must not be reentered, so we do this 2392570Swnj * at high ipl. 2402570Swnj */ 24140Sbill npf = (mr >> 18) & 0x3ff; 24240Sbill reg = ((mr >> 9) & 0x1ff) + 1; 2432570Swnj s = spl6(); 2442784Swnj rmfree(uh->uh_map, npf, reg); 2452570Swnj splx(s); 2462570Swnj 2472570Swnj /* 2482570Swnj * Wakeup sleepers for map registers, 2492570Swnj * and also, if there are processes blocked in dgo(), 2502570Swnj * give them a chance at the UNIBUS. 2512570Swnj */ 2522395Swnj if (uh->uh_mrwant) { 2532395Swnj uh->uh_mrwant = 0; 2542395Swnj wakeup((caddr_t)uh->uh_map); 25540Sbill } 2562570Swnj while (uh->uh_actf && ubago(uh->uh_actf)) 2572570Swnj ; 25840Sbill } 25940Sbill 2602729Swnj ubapurge(um) 261*2958Swnj register struct uba_ctlr *um; 2622729Swnj { 2632729Swnj register struct uba_hd *uh = um->um_hd; 2642729Swnj register int bdp = (um->um_ubinfo >> 28) & 0x0f; 2652729Swnj 2662729Swnj switch (cpu) { 2672729Swnj #if VAX780 2682729Swnj case VAX_780: 269*2958Swnj uh->uh_uba->uba_dpr[bdp] |= UBADPR_BNE; 2702729Swnj break; 2712729Swnj #endif 2722729Swnj #if VAX750 2732729Swnj case VAX_750: 274*2958Swnj uh->uh_uba->uba_dpr[bdp] |= UBADPR_PURGE|UBADPR_NXM|UBADPR_UCE; 2752729Swnj break; 2762729Swnj #endif 2772729Swnj } 2782729Swnj } 2792729Swnj 2802570Swnj /* 2812570Swnj * Generate a reset on uba number uban. Then 2822570Swnj * call each device in the character device table, 2832570Swnj * giving it a chance to clean up so as to be able to continue. 2842570Swnj */ 2852395Swnj ubareset(uban) 2862570Swnj int uban; 287284Sbill { 288284Sbill register struct cdevsw *cdp; 2892646Swnj register struct uba_hd *uh = &uba_hd[uban]; 2901781Sbill int s; 291284Sbill 292302Sbill s = spl6(); 2932646Swnj uh->uh_users = 0; 2942646Swnj uh->uh_zvcnt = 0; 2952646Swnj uh->uh_xclu = 0; 2962646Swnj uh->uh_hangcnt = 0; 2972646Swnj uh->uh_actf = uh->uh_actl = 0; 2982646Swnj uh->uh_bdpwant = 0; 2992646Swnj uh->uh_mrwant = 0; 3002646Swnj wakeup((caddr_t)&uh->uh_bdpwant); 3012646Swnj wakeup((caddr_t)&uh->uh_mrwant); 302*2958Swnj printf("uba%d: reset", uban); 303*2958Swnj ubainit(uh->uh_uba); 304284Sbill for (cdp = cdevsw; cdp->d_open; cdp++) 3052395Swnj (*cdp->d_reset)(uban); 306284Sbill printf("\n"); 307302Sbill splx(s); 308284Sbill } 3092395Swnj 3102570Swnj /* 3112570Swnj * Init a uba. This is called with a pointer 3122570Swnj * rather than a virtual address since it is called 3132570Swnj * by code which runs with memory mapping disabled. 3142570Swnj * In these cases we really don't need the interrupts 3152570Swnj * enabled, but since we run with ipl high, we don't care 3162570Swnj * if they are, they will never happen anyways. 3172570Swnj */ 3182423Skre ubainit(uba) 3192423Skre register struct uba_regs *uba; 3202395Swnj { 3212395Swnj 322*2958Swnj switch (cpu) { 323*2958Swnj #if VAX780 324*2958Swnj case VAX780: 325*2958Swnj uba->uba_cr = UBACR_ADINIT; 326*2958Swnj uba->uba_cr = UBACR_IFS|UBACR_BRIE|UBACR_USEFIE|UBACR_SUEFIE; 327*2958Swnj while ((uba->uba_cnfgr & UBACNFGR_UBIC) == 0) 328*2958Swnj ; 329*2958Swnj break; 330*2958Swnj #endif 331*2958Swnj #if VAX750 332*2958Swnj case VAX750: 333*2958Swnj mtpr(IUR, 1); 334*2958Swnj /* give devices time to recover from power fail */ 335*2958Swnj DELAY(5000000); 336*2958Swnj break; 337*2958Swnj #endif 338*2958Swnj } 3392395Swnj } 3402395Swnj 341*2958Swnj #if VAX780 3422570Swnj /* 3432570Swnj * Check to make sure the UNIBUS adaptor is not hung, 3442570Swnj * with an interrupt in the register to be presented, 3452570Swnj * but not presenting it for an extended period (5 seconds). 3462570Swnj */ 3472395Swnj unhang() 3482395Swnj { 3492395Swnj register int uban; 3502395Swnj 3512395Swnj for (uban = 0; uban < numuba; uban++) { 3522395Swnj register struct uba_hd *uh = &uba_hd[uban]; 3532395Swnj register struct uba_regs *up = uh->uh_uba; 3542395Swnj 3552395Swnj if (up->uba_sr == 0) 3562395Swnj return; 3572395Swnj uh->uh_hangcnt++; 3582759Swnj if (uh->uh_hangcnt > 5*hz) { 3592395Swnj uh->uh_hangcnt = 0; 3602929Swnj printf("uba%d: hung\n", uban); 3612395Swnj ubareset(uban); 3622395Swnj } 3632395Swnj } 3642395Swnj } 3652395Swnj 3662570Swnj /* 3672570Swnj * This is a timeout routine which decrements the ``i forgot to 3682570Swnj * interrupt'' counts, on an 11/780. This prevents slowly growing 3692570Swnj * counts from causing a UBA reset since we are interested only 3702570Swnj * in hang situations. 3712570Swnj */ 3722395Swnj ubawatch() 3732395Swnj { 3742395Swnj register struct uba_hd *uh; 3752395Swnj register int uban; 3762395Swnj 3772784Swnj if (panicstr) 3782784Swnj return; 3792395Swnj for (uban = 0; uban < numuba; uban++) { 3802395Swnj uh = &uba_hd[uban]; 3812395Swnj if (uh->uh_hangcnt) 3822395Swnj uh->uh_hangcnt--; 3832395Swnj } 3842395Swnj } 3852395Swnj 3862570Swnj /* 3872570Swnj * This routine is called by the locore code to 3882570Swnj * process a UBA error on an 11/780. The arguments are passed 3892570Swnj * on the stack, and value-result (through some trickery). 3902570Swnj * In particular, the uvec argument is used for further 3912570Swnj * uba processing so the result aspect of it is very important. 3922570Swnj * It must not be declared register. 3932570Swnj */ 3942423Skre /*ARGSUSED*/ 3952395Swnj ubaerror(uban, uh, xx, uvec, uba) 3962395Swnj register int uban; 3972395Swnj register struct uba_hd *uh; 3982395Swnj int uvec; 3992395Swnj register struct uba_regs *uba; 4002395Swnj { 4012395Swnj register sr, s; 4022395Swnj 4032395Swnj if (uvec == 0) { 4042395Swnj uh->uh_zvcnt++; 4052395Swnj if (uh->uh_zvcnt > 250000) { 4062929Swnj printf("uba%d: too many zero vectors\n"); 4072395Swnj ubareset(uban); 4082395Swnj } 4092395Swnj uvec = 0; 4102395Swnj return; 4112395Swnj } 4122395Swnj if (uba->uba_cnfgr & NEX_CFGFLT) { 4132929Swnj printf("uba%d: sbi fault sr=%b cnfgr=%b\n", 4142929Swnj uban, uba->uba_sr, ubasr_bits, 4152929Swnj uba->uba_cnfgr, nexflt_bits); 4162395Swnj ubareset(uban); 4172395Swnj uvec = 0; 4182395Swnj return; 4192395Swnj } 4202395Swnj sr = uba->uba_sr; 4212395Swnj s = spl7(); 4222929Swnj printf("uba%d: uba error sr=%x fmer=%x fubar=%o\n", 4232470Swnj uban, uba->uba_sr, uba->uba_fmer, 4*uba->uba_fubar); 4242395Swnj splx(s); 4252395Swnj uba->uba_sr = sr; 426*2958Swnj uvec &= UBABRRVR_DIV; 4272395Swnj return; 4282395Swnj } 4292395Swnj #endif 430