📄 uba.c
字号:
if (pte) pte++; else mips_pfn++; }#else if (user_addr && (((int)pte & PGOFSET) < CLSIZE*sizeof(struct pte) || pte->pg_pfnum == 0)) pte = vtopte(rp, v); if (pte->pg_pfnum == 0) panic("uba zero uentry"); *(int *)io++ = pte++->pg_pfnum | temp; v++;#endif mips } *(int *)io++ = 0; /* Set up fire wall */ WBFLUSH; } else { ubinfo = contigphys( ubinfo, bp->b_bcount, pte); ++reg; a = spl6(); rmfree( uh->uh_map, (long)npf, (long)reg); splx(a); } return (ubinfo);}/* * Non buffer setup interface... set up a buffer and call ubasetup. */uballoc(uban, addr, bcnt, flags) int uban; caddr_t addr; int bcnt, flags;{ struct buf ubabuf; ubabuf.b_un.b_addr = addr; ubabuf.b_flags = B_BUSY; ubabuf.b_bcount = bcnt; /* that's all the fields ubasetup() needs */ return (ubasetup(uban, &ubabuf, flags));} /* * Release resources on uba uban, and then unblock resource waiters. * The map register parameter is by value since we need to block * against uba resets on 11/780's. */ubarelse(uban, amr) int *amr;{ register struct uba_hd *uh = &uba_hd[uban]; register int bdp, reg, npf, s; int mr; /* * Carefully see if we should release the space, since * it may be released asynchronously at uba reset time. */ s = spl6(); mr = *amr; if (mr == 0) { /* * A ubareset() occurred before we got around * to releasing the space... no need to bother. */ splx(s); return; } *amr = 0; splx(s); /* let interrupts in, we're safe for a while */ bdp = (mr >> 28) & 0x0f; if (bdp) { if (uh->uba_type&UBABUA){ bdp = bdp & 0x07; ((struct bua_regs *)uh->uh_uba)->bua_dpr[bdp] |= BUADPR_PURGE; } else if (uh->uba_type&UBA780) uh->uh_uba->uba_dpr[bdp] |= UBADPR_BNE; else if (uh->uba_type&UBA750) uh->uh_uba->uba_dpr[bdp] |= UBADPR_PURGE|UBADPR_NXM|UBADPR_UCE; uh->uh_bdpfree |= 1 << (bdp-1); /* atomic */ if (uh->uh_bdpwant) { uh->uh_bdpwant = 0; wakeup((caddr_t)&uh->uh_bdpwant); } } /* * Put back the registers in the resource map. * The map code must not be reentered, so we do this * at high ipl. */ npf = (mr >> 18) & 0x3ff; reg = ((mr >> 9) & 0x1ff) + 1; s = spl6(); rmfree(uh->uh_map, (long)npf, (long)reg); splx(s); /* * Wakeup sleepers for map registers, * and also, if there are processes blocked in dgo(), * give them a chance at the UNIBUS. */ if (uh->uh_mrwant) { uh->uh_mrwant = 0; wakeup((caddr_t)&uh->uh_mrwant); } while (uh->uh_actf && ubago(uh->uh_actf)) ;}ubapurge(um) register struct uba_ctlr *um;{ register struct uba_hd *uh = um->um_hd; register int bdp = (um->um_ubinfo >> 28) & 0x0f; if (uh->uba_type & UBABUA) { bdp = bdp & 0x07; ((struct bua_regs *)uh->uh_uba)->bua_dpr[bdp] |= BUADPR_PURGE; } else if (uh->uba_type & UBA780) uh->uh_uba->uba_dpr[bdp] |= UBADPR_BNE; else if (uh->uba_type & UBA750) uh->uh_uba->uba_dpr[bdp]|=UBADPR_PURGE|UBADPR_NXM|UBADPR_UCE;}ubainitmaps(uhp) register struct uba_hd *uhp;{ rminit(uhp->uh_map, (long)NUBMREG, (long)1, "uba", UAMSIZ); if (uhp->uba_type&UBABUA) uhp->uh_bdpfree = (1<<NBDP_BUA) - 1; else if(uhp->uba_type & UBA780) uhp->uh_bdpfree = (1<<NBDP8600) - 1; else if(uhp->uba_type & UBA750) uhp->uh_bdpfree = (1<<NBDP750) - 1;}/* * Generate a reset on uba number uban. Then * call each device in the character device table, * giving it a chance to clean up so as to be able to continue. */ubareset(uban) int uban;{ register struct cdevsw *cdp; register struct uba_hd *uh = &uba_hd[uban]; int s; s = spl6(); uh->uh_users = 0; uh->uh_zvcnt = 0; uh->uh_xclu = 0; uh->uh_actf = uh->uh_actl = 0; uh->uh_bdpwant = 0; uh->uh_mrwant = 0; ubainitmaps(uh); wakeup((caddr_t)&uh->uh_bdpwant); wakeup((caddr_t)&uh->uh_mrwant); if (uh->uba_type & UBABDA) { printf("bda%d: reset",uban); } else if (uh->uba_type & UBAXMI) { printf("kdm%d: reset",uban); } else { printf("uba%d: reset", uban); ubainit(uh->uh_uba,uh->uba_type); } /* reallocate global unibus space for tty drivers */ if (tty_ubinfo[uban] != 0) tty_ubinfo[uban] = uballoc(uban, (caddr_t)cfree, nclist*sizeof (struct cblock), 0); for (cdp = cdevsw; cdp < cdevsw + nchrdev; cdp++) (*cdp->d_reset)(uban);#ifdef INET ifubareset(uban);#endif printf("\n"); splx(s);}/* * Init a uba. This is called with a pointer * rather than a virtual address since it is called * by code which runs with memory mapping disabled. * In these cases we really don't need the interrupts * enabled, but since we run with ipl high, we don't care * if they are, they will never happen anyways. */ubainit(uba,ubatype) register int ubatype; register struct uba_regs *uba;{ extern struct ssc_regs *ssc_ptr; if (ubatype&UBA780) { uba->uba_cr = UBACR_ADINIT; uba->uba_cr = UBACR_IFS|UBACR_BRIE|UBACR_USEFIE|UBACR_SUEFIE; while ((uba->uba_cnfgr & UBACNFGR_UBIC) == 0) ; } else if (ubatype&UBABUA) buainit(uba);#ifdef vax else if (ubatype&(UBA750|UBA730|UBAUVI)) { mtpr(IUR, 0); /* give devices time to recover from power fail */ DELAY(500000); }#endif vax else if (ubatype&UBAUVII) {#define LMEA 0x20 /* Local memory access enable */#define QIPCR 0x1f40 /* Q-bus Inter-processor csr */ /* * Reset the bus and wait for the devices to * settle down */#ifdef vax mtpr(IUR, 0);#endif vax#ifdef mips ssc_ptr->ssc_ioreset = 0; /* equiv to mtpr(IUR, 0) */#endif mips DELAY(500000); /* * The bus reset turns off the q-bus map (unfortunately) * The problem is further agravated by the fact that the * enable bit is in the IPC register which is in I/O space * instead of local register space. Because of this we * have to figure out if we're virtual or physical. */#ifdef vax if( mfpr(MAPEN) & 0x1 ) { /* * Virtual */ *(u_short *)((char *)qmem+QMEMSIZEUVI+QIPCR) = LMEA; } else { /* * Physical */ *(u_short *)((char *)QDEVADDRUVI+QIPCR) = LMEA; }#endif vax#ifdef mips /* * We are on a Qbus mips machine. The bus reset we just * did turned off the Qbus map. We need to allow * external access to Qbus memory space via the Qbus map. * Since on a mips we always have memory management, * we access the IPCR (implemented in the CQBIC chip) * through Kseg 1 space * * IPCR is a 16-bit register located in offset * 0x1f40 from the Q bus I/O space. */ *(u_short *)((char *)qmem+QMEMSIZEUVI+QIPCR) = LMEA;#endif mips }}int ubawedgecnt = 10;int ubacrazy = 500;/* * This routine is called by the locore code to * process a UBA error on an 11/780. The arguments are passed * on the stack, and value-result (through some trickery). * In particular, the uvec argument is used for further * uba processing so the result aspect of it is very important. * It must not be declared register. *//*ARGSUSED*/ubaerror(uban, uh, xx, uvec, uba, ubapc) register int uban; register struct uba_hd *uh; int uvec; register struct uba_regs *uba; int *ubapc;{ register int sr, s; struct el_rec *elrp; /* * Start a timer to time the rate of zero vectors. * The counting is done in locore.s. */ if (uvec == 0) { if (uh->uh_zvflg) mprintf("ubaerror: zero vector flag shouldn't be set\n"); else { uh->uh_zvcnt++; uh->uh_zvflg++; timeout(ubatimer, uban, hz * zvintvl); } return; } if (uh->uba_type&UBABUA) { sr = ((struct bua_regs *)uh->uh_uba)->bua_ctrl; s = spl7(); printf("bua%d: bua error ctrl=%x",uban,sr); splx(s); ((struct bua_regs *)uh->uh_uba)->bua_ctrl = sr; ubareset(uban); } else if ((uh->uba_type&UBABDA)==0) { if (uba->uba_cnfgr & NEX_CFGFLT) { elrp = ealloc(EL_UBASIZE,EL_PRILOW); if (elrp != NULL) { LSUBID(elrp,ELCT_ADPTR,ELADP_UBA,EL_UNDEF,EL_UNDEF,uban,EL_UNDEF); elrp->el_body.eluba780.uba_cf = uba->uba_cnfgr; elrp->el_body.eluba780.uba_cr = uba->uba_cr; elrp->el_body.eluba780.uba_sr = uba->uba_sr; elrp->el_body.eluba780.uba_dcr = uba->uba_dcr; elrp->el_body.eluba780.uba_fmer = uba->uba_fmer; elrp->el_body.eluba780.uba_fubar = uba->uba_fubar; elrp->el_body.eluba780.uba_pc = *ubapc; elrp->el_body.eluba780.uba_psl = *++ubapc; EVALID(elrp); } else { cprintf("uba%d: sbi fault sr=%b cnfgr=%b\n", uban, uba->uba_sr, ubasr_bits, uba->uba_cnfgr, NEXFLT_BITS); } ubareset(uban); uvec = 0; return; } sr = uba->uba_sr; s = spl7(); elrp = ealloc(EL_UBASIZE,EL_PRILOW); if (elrp != NULL) { LSUBID(elrp,ELCT_ADPTR,ELADP_UBA,EL_UNDEF,EL_UNDEF,uban,EL_UNDEF); elrp->el_body.eluba780.uba_cf = uba->uba_cnfgr; elrp->el_body.eluba780.uba_cr = uba->uba_cr; elrp->el_body.eluba780.uba_sr = uba->uba_sr; elrp->el_body.eluba780.uba_dcr = uba->uba_dcr; elrp->el_body.eluba780.uba_fmer = uba->uba_fmer; elrp->el_body.eluba780.uba_fubar = uba->uba_fubar; elrp->el_body.eluba780.uba_pc = *ubapc; elrp->el_body.eluba780.uba_psl = *++ubapc; EVALID(elrp); } else { cprintf("uba%d: uba error sr=%b fmer=%x fubar=%o\n", uban, uba->uba_sr, ubasr_bits, uba->uba_fmer, 4*uba->uba_fubar); } splx(s); uba->uba_sr = sr; uvec &= UBABRRVR_DIV; } if (++uh->uh_errcnt % ubawedgecnt == 0) { if (uh->uh_errcnt > ubacrazy) panic("uba crazy"); printf("ERROR LIMIT "); ubareset(uban); uvec = 0; return; } return;}/* * Allocate UNIBUS memory. Allocates and initializes * sufficient mapping registers for access. On a 780, * the configuration register is setup to disable UBA * response on DMA transfers to addresses controlled * by the disabled mapping registers. */ubamem(uban, addr, npg, doalloc) int uban, addr, npg, doalloc;{ register struct uba_hd *uh = &uba_hd[uban]; register int a; if (doalloc) { int s = spl6(); a = rmget(uh->uh_map, npg, (addr >> 9) + 1); splx(s); } else a = (addr >> 9) + 1; if (a) { register int i, *m; m = (int *)&uh->uh_uba->uba_map[a - 1]; for (i = 0; i < npg; i++) *m++ = 0; /* All off, especially 'valid' */ /* * On a 780 and 8600, set up the map register disable
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -