1*2616Swnj /* uba.c 4.12 02/22/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" 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" 192570Swnj #include "../h/dk.h" 2040Sbill 21*2616Swnj #include "rk.h" 22*2616Swnj #if NRK11 > 0 23*2616Swnj extern struct uba_driver hkdriver; 24*2616Swnj #endif 25*2616Swnj 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) 402570Swnj register struct uba_dinfo *ui; 412570Swnj { 422570Swnj register struct uba_minfo *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(); 48*2616Swnj #if NRK11 > 0 49*2616Swnj if (um->um_driver == &hkdriver && uh->uh_users > 0 || uh->uh_xclu) 50*2616Swnj goto rwait; 51*2616Swnj #endif 522570Swnj um->um_ubinfo = ubasetup(um->um_ubanum, um->um_tab.b_actf->b_actf, 532570Swnj UBA_NEEDBDP|UBA_CANTWAIT); 54*2616Swnj if (um->um_ubinfo == 0) 55*2616Swnj goto rwait; 56*2616Swnj #if NRK11 > 0 57*2616Swnj uh->uh_users++; 58*2616Swnj if (um->um_driver == &hkdriver) 59*2616Swnj uh->uh_xclu = 1; 60*2616Swnj #endif 612570Swnj splx(s); 622570Swnj if (ui->ui_dk >= 0) { 632570Swnj unit = ui->ui_dk; 642570Swnj dk_busy |= 1<<unit; 652570Swnj } 662570Swnj if (uh->uh_actf == ui) 672570Swnj uh->uh_actf = ui->ui_forw; 682570Swnj (*um->um_driver->ud_dgo)(um); 692570Swnj if (ui->ui_dk >= 0) { 702570Swnj dk_xfer[unit]++; 712570Swnj dk_wds[unit] += um->um_tab.b_actf->b_bcount>>6; 722570Swnj } 732570Swnj return (1); 74*2616Swnj rwait: 75*2616Swnj if (uh->uh_actf != ui) { 76*2616Swnj ui->ui_forw = NULL; 77*2616Swnj if (uh->uh_actf == NULL) 78*2616Swnj uh->uh_actf = ui; 79*2616Swnj else 80*2616Swnj uh->uh_actl->ui_forw = ui; 81*2616Swnj uh->uh_actl = ui; 82*2616Swnj } 83*2616Swnj splx(s); 84*2616Swnj return (0); 852570Swnj } 862570Swnj 87*2616Swnj ubadone(um) 88*2616Swnj register struct uba_minfo *um; 89*2616Swnj { 90*2616Swnj register struct uba_hd *uh = &uba_hd[um->um_ubanum]; 91*2616Swnj 92*2616Swnj #if NRK11 > 0 93*2616Swnj if (um->um_driver == &hkdriver) 94*2616Swnj uh->uh_xclu = 0; 95*2616Swnj uh->uh_users--; 96*2616Swnj #endif 97*2616Swnj ubarelse(um->um_ubanum, &um->um_ubinfo); 98*2616Swnj } 99*2616Swnj 1002570Swnj /* 1012395Swnj * Allocate and setup UBA map registers, and bdp's 1022395Swnj * Flags says whether bdp is needed, whether the caller can't 1032395Swnj * wait (e.g. if the caller is at interrupt level). 10440Sbill * 1052570Swnj * Return value: 10640Sbill * Bits 0-8 Byte offset 10740Sbill * Bits 9-17 Start map reg. no. 10840Sbill * Bits 18-27 No. mapping reg's 10940Sbill * Bits 28-31 BDP no. 11040Sbill */ 1112395Swnj ubasetup(uban, bp, flags) 1122395Swnj struct buf *bp; 11340Sbill { 1142395Swnj register struct uba_hd *uh = &uba_hd[uban]; 11540Sbill register int temp, i; 11640Sbill int npf, reg, bdp; 11740Sbill unsigned v; 11840Sbill register struct pte *pte, *io; 11940Sbill struct proc *rp; 12040Sbill int a, o, ubinfo; 12140Sbill 12240Sbill v = btop(bp->b_un.b_addr); 12340Sbill o = (int)bp->b_un.b_addr & PGOFSET; 12440Sbill npf = btoc(bp->b_bcount + o) + 1; 12540Sbill a = spl6(); 1262395Swnj while ((reg = malloc(uh->uh_map, npf)) == 0) { 1272395Swnj if (flags & UBA_CANTWAIT) 1282395Swnj return (0); 1292395Swnj uh->uh_mrwant++; 1302395Swnj sleep((caddr_t)uh->uh_map, PSWP); 13140Sbill } 13240Sbill bdp = 0; 1332395Swnj if (flags & UBA_NEEDBDP) { 1342395Swnj while ((bdp = ffs(uh->uh_bdpfree)) == 0) { 1352395Swnj if (flags & UBA_CANTWAIT) { 1362395Swnj mfree(uh->uh_map, npf, reg); 1372395Swnj return (0); 1382395Swnj } 1392395Swnj uh->uh_bdpwant++; 1402395Swnj sleep((caddr_t)uh->uh_map, PSWP); 14140Sbill } 1422463Swnj uh->uh_bdpfree &= ~(1 << (bdp-1)); 1432395Swnj } 14440Sbill splx(a); 1452463Swnj reg--; 14640Sbill ubinfo = (bdp << 28) | (npf << 18) | (reg << 9) | o; 1472395Swnj io = &uh->uh_uba->uba_map[reg]; 1482395Swnj temp = (bdp << 21) | UBA_MRV; 14940Sbill rp = bp->b_flags&B_DIRTY ? &proc[2] : bp->b_proc; 15040Sbill if (bdp && (o & 01)) 1512395Swnj temp |= UBA_BO; 15240Sbill if (bp->b_flags & B_UAREA) { 15340Sbill for (i = UPAGES - bp->b_bcount / NBPG; i < UPAGES; i++) { 15440Sbill if (rp->p_addr[i].pg_pfnum == 0) 15540Sbill panic("uba: zero upage"); 15640Sbill *(int *)io++ = rp->p_addr[i].pg_pfnum | temp; 15740Sbill } 15840Sbill } else if ((bp->b_flags & B_PHYS) == 0) { 159728Sbill pte = &Sysmap[btop(((int)bp->b_un.b_addr)&0x7fffffff)]; 16040Sbill while (--npf != 0) 161728Sbill *(int *)io++ = pte++->pg_pfnum | temp; 16240Sbill } else { 16340Sbill if (bp->b_flags & B_PAGET) 16440Sbill pte = &Usrptmap[btokmx((struct pte *)bp->b_un.b_addr)]; 16540Sbill else 16640Sbill pte = vtopte(rp, v); 16740Sbill while (--npf != 0) { 16840Sbill if (pte->pg_pfnum == 0) 16940Sbill panic("uba zero uentry"); 17040Sbill *(int *)io++ = pte++->pg_pfnum | temp; 17140Sbill } 17240Sbill } 17340Sbill *(int *)io++ = 0; 17440Sbill return (ubinfo); 17540Sbill } 17640Sbill 17740Sbill /* 1782570Swnj * Non buffer setup interface... set up a buffer and call ubasetup. 17940Sbill */ 1802395Swnj uballoc(uban, addr, bcnt, flags) 18140Sbill caddr_t addr; 18240Sbill unsigned short bcnt; 18340Sbill { 184883Sbill struct buf ubabuf; 18540Sbill 18640Sbill ubabuf.b_un.b_addr = addr; 18740Sbill ubabuf.b_flags = B_BUSY; 18840Sbill ubabuf.b_bcount = bcnt; 189883Sbill /* that's all the fields ubasetup() needs */ 1902395Swnj return (ubasetup(uban, &ubabuf, flags)); 19140Sbill } 19240Sbill 1932053Swnj /* 1942570Swnj * Release resources on uba uban, and then unblock resource waiters. 1952570Swnj * The map register parameter is by value since we need to block 1962570Swnj * against uba resets on 11/780's. 1972053Swnj */ 1982395Swnj ubarelse(uban, amr) 1992053Swnj int *amr; 20040Sbill { 2012395Swnj register struct uba_hd *uh = &uba_hd[uban]; 2022570Swnj register int bdp, reg, npf, s; 2032053Swnj int mr; 20440Sbill 2052570Swnj /* 2062570Swnj * Carefully see if we should release the space, since 2072570Swnj * it may be released asynchronously at uba reset time. 2082570Swnj */ 2092570Swnj s = spl6(); 2102053Swnj mr = *amr; 2112053Swnj if (mr == 0) { 2122570Swnj /* 2132570Swnj * A ubareset() occurred before we got around 2142570Swnj * to releasing the space... no need to bother. 2152570Swnj */ 2162570Swnj splx(s); 2172053Swnj return; 2182053Swnj } 2192067Swnj *amr = 0; 2202570Swnj splx(s); /* let interrupts in, we're safe for a while */ 22140Sbill bdp = (mr >> 28) & 0x0f; 22240Sbill if (bdp) { 2232423Skre switch (cpu) 2242423Skre { 2252423Skre #if VAX780 2262423Skre case VAX_780: 2272423Skre uh->uh_uba->uba_dpr[bdp] |= UBA_BNE; 2282423Skre break; 2292423Skre #endif 2302423Skre #if VAX750 2312423Skre case VAX_750: 2322423Skre uh->uh_uba->uba_dpr[bdp] |= UBA_PURGE|UBA_NXM|UBA_UCE; 2332423Skre break; 2342423Skre #endif 2352423Skre } 2362570Swnj uh->uh_bdpfree |= 1 << (bdp-1); /* atomic */ 2372395Swnj if (uh->uh_bdpwant) { 2382395Swnj uh->uh_bdpwant = 0; 2392395Swnj wakeup((caddr_t)uh->uh_map); 24040Sbill } 24140Sbill } 2422570Swnj /* 2432570Swnj * Put back the registers in the resource map. 2442570Swnj * The map code must not be reentered, so we do this 2452570Swnj * at high ipl. 2462570Swnj */ 24740Sbill npf = (mr >> 18) & 0x3ff; 24840Sbill reg = ((mr >> 9) & 0x1ff) + 1; 2492570Swnj s = spl6(); 2502395Swnj mfree(uh->uh_map, npf, reg); 2512570Swnj splx(s); 2522570Swnj 2532570Swnj /* 2542570Swnj * Wakeup sleepers for map registers, 2552570Swnj * and also, if there are processes blocked in dgo(), 2562570Swnj * give them a chance at the UNIBUS. 2572570Swnj */ 2582395Swnj if (uh->uh_mrwant) { 2592395Swnj uh->uh_mrwant = 0; 2602395Swnj wakeup((caddr_t)uh->uh_map); 26140Sbill } 2622570Swnj while (uh->uh_actf && ubago(uh->uh_actf)) 2632570Swnj ; 26440Sbill } 26540Sbill 2662570Swnj /* 2672570Swnj * Generate a reset on uba number uban. Then 2682570Swnj * call each device in the character device table, 2692570Swnj * giving it a chance to clean up so as to be able to continue. 2702570Swnj */ 2712395Swnj ubareset(uban) 2722570Swnj int uban; 273284Sbill { 274284Sbill register struct cdevsw *cdp; 2751781Sbill int s; 276284Sbill 277302Sbill s = spl6(); 2782395Swnj switch (cpu) { 2791901Swnj #if VAX==780 2802395Swnj case VAX_780: 2812395Swnj printf("UBA RESET %d:", uban); 2822395Swnj ubainit(uba_hd[uban].uh_uba); 2832395Swnj break; 2841901Swnj #endif 2851901Swnj #if VAX==750 2862395Swnj case VAX_750: 2872395Swnj printf("UNIBUS INIT:"); 2882395Swnj mtpr(IUR, 1); 2892395Swnj DELAY(100000); 2902395Swnj break; 2911901Swnj #endif 2922395Swnj } 293284Sbill for (cdp = cdevsw; cdp->d_open; cdp++) 2942395Swnj (*cdp->d_reset)(uban); 295284Sbill printf("\n"); 296302Sbill splx(s); 297284Sbill } 2982395Swnj 2992570Swnj /* 3002570Swnj * Init a uba. This is called with a pointer 3012570Swnj * rather than a virtual address since it is called 3022570Swnj * by code which runs with memory mapping disabled. 3032570Swnj * In these cases we really don't need the interrupts 3042570Swnj * enabled, but since we run with ipl high, we don't care 3052570Swnj * if they are, they will never happen anyways. 3062570Swnj */ 3072423Skre ubainit(uba) 3082423Skre register struct uba_regs *uba; 3092395Swnj { 3102395Swnj 3112423Skre uba->uba_cr = UBA_ADINIT; 3122423Skre uba->uba_cr = UBA_IFS|UBA_BRIE|UBA_USEFIE|UBA_SUEFIE; 3132423Skre while ((uba->uba_cnfgr & UBA_UBIC) == 0) 3142395Swnj ; 3152395Swnj } 3162395Swnj 3172395Swnj #if VAX780 3182570Swnj /* 3192570Swnj * Check to make sure the UNIBUS adaptor is not hung, 3202570Swnj * with an interrupt in the register to be presented, 3212570Swnj * but not presenting it for an extended period (5 seconds). 3222570Swnj */ 3232395Swnj unhang() 3242395Swnj { 3252395Swnj register int uban; 3262395Swnj 3272395Swnj for (uban = 0; uban < numuba; uban++) { 3282395Swnj register struct uba_hd *uh = &uba_hd[uban]; 3292395Swnj register struct uba_regs *up = uh->uh_uba; 3302395Swnj 3312395Swnj if (up->uba_sr == 0) 3322395Swnj return; 3332395Swnj uh->uh_hangcnt++; 3342395Swnj if (uh->uh_hangcnt > 5*HZ) { 3352395Swnj uh->uh_hangcnt = 0; 3362395Swnj printf("HANG "); 3372395Swnj ubareset(uban); 3382395Swnj } 3392395Swnj } 3402395Swnj } 3412395Swnj 3422570Swnj /* 3432570Swnj * This is a timeout routine which decrements the ``i forgot to 3442570Swnj * interrupt'' counts, on an 11/780. This prevents slowly growing 3452570Swnj * counts from causing a UBA reset since we are interested only 3462570Swnj * in hang situations. 3472570Swnj */ 3482395Swnj ubawatch() 3492395Swnj { 3502395Swnj register struct uba_hd *uh; 3512395Swnj register int uban; 3522395Swnj 3532395Swnj for (uban = 0; uban < numuba; uban++) { 3542395Swnj uh = &uba_hd[uban]; 3552395Swnj if (uh->uh_hangcnt) 3562395Swnj uh->uh_hangcnt--; 3572395Swnj } 3582395Swnj } 3592395Swnj 3602570Swnj /* 3612570Swnj * This routine is called by the locore code to 3622570Swnj * process a UBA error on an 11/780. The arguments are passed 3632570Swnj * on the stack, and value-result (through some trickery). 3642570Swnj * In particular, the uvec argument is used for further 3652570Swnj * uba processing so the result aspect of it is very important. 3662570Swnj * It must not be declared register. 3672570Swnj */ 3682423Skre /*ARGSUSED*/ 3692395Swnj ubaerror(uban, uh, xx, uvec, uba) 3702395Swnj register int uban; 3712395Swnj register struct uba_hd *uh; 3722395Swnj int uvec; 3732395Swnj register struct uba_regs *uba; 3742395Swnj { 3752395Swnj register sr, s; 3762395Swnj 3772395Swnj if (uvec == 0) { 3782395Swnj uh->uh_zvcnt++; 3792395Swnj if (uh->uh_zvcnt > 250000) { 3802395Swnj printf("ZERO VECTOR "); 3812395Swnj ubareset(uban); 3822395Swnj } 3832395Swnj uvec = 0; 3842395Swnj return; 3852395Swnj } 3862395Swnj if (uba->uba_cnfgr & NEX_CFGFLT) { 3872395Swnj printf("UBA%d SBI FAULT sr %x cnfgr %x\n", 3882395Swnj uban, uba->uba_sr, uba->uba_cnfgr); 3892395Swnj ubareset(uban); 3902395Swnj uvec = 0; 3912395Swnj return; 3922395Swnj } 3932395Swnj sr = uba->uba_sr; 3942395Swnj s = spl7(); 3952395Swnj printf("UBA%d ERROR SR %x FMER %x FUBAR %o\n", 3962470Swnj uban, uba->uba_sr, uba->uba_fmer, 4*uba->uba_fubar); 3972395Swnj splx(s); 3982395Swnj uba->uba_sr = sr; 3992395Swnj uvec &= UBA_DIV; 4002395Swnj return; 4012395Swnj } 4022395Swnj #endif 403