📄 uba.c
字号:
}ubainitmaps(uhp) register struct uba_hd *uhp;{ if (uhp->uh_memsize > UBA_MAXMR) uhp->uh_memsize = UBA_MAXMR; rminit(uhp->uh_map, (long)uhp->uh_memsize, (long)1, "uba", UAMSIZ); switch (uhp->uh_type) {#ifdef DWBUA case DWBUA: uhp->uh_bdpfree = (1<<NBDPBUA) - 1; break;#endif#ifdef DW780 case DW780: uhp->uh_bdpfree = (1<<NBDP780) - 1; break;#endif#ifdef DW750 case DW750: uhp->uh_bdpfree = (1<<NBDP750) - 1; break;#endif default: break; }}/* * 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 = spluba(); 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); printf("uba%d: reset", uban); ubainit(uh->uh_uba); ubameminit(uban); for (cdp = cdevsw; cdp < cdevsw + nchrdev; cdp++) (*cdp->d_reset)(uban); ifubareset(uban); 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. * SHOULD GET POINTER TO UBA_HD INSTEAD OF UBA. */ubainit(uba) register struct uba_regs *uba;{ register struct uba_hd *uhp;#ifdef QBA int isphys = 0;#endif for (uhp = uba_hd; uhp < uba_hd + numuba; uhp++) { if (uhp->uh_uba == uba) break; if (uhp->uh_physuba == uba) {#ifdef QBA isphys++;#endif break; } } if (uhp >= uba_hd + numuba) { printf("init unknown uba\n"); return; } switch (uhp->uh_type) {#ifdef DWBUA case DWBUA: BUA(uba)->bua_csr |= BUACSR_UPI; /* give devices time to recover from power fail */ DELAY(500000); break;#endif#ifdef DW780 case DW780: uba->uba_cr = UBACR_ADINIT; uba->uba_cr = UBACR_IFS|UBACR_BRIE|UBACR_USEFIE|UBACR_SUEFIE; while ((uba->uba_cnfgr & UBACNFGR_UBIC) == 0) ; break;#endif#ifdef DW750 case DW750:#endif#ifdef DW730 case DW730:#endif#ifdef QBA case QBA:#endif#if DW750 || DW730 || QBA mtpr(IUR, 0); /* give devices time to recover from power fail *//* THIS IS PROBABLY UNNECESSARY */ DELAY(500000);/* END PROBABLY UNNECESSARY */#ifdef QBA /* * Re-enable local memory access * from the Q-bus. */ if (uhp->uh_type == QBA) { if (isphys) *((char *)QIOPAGE630 + QIPCR) = Q_LMEAE; else *(uhp->uh_iopage + QIPCR) = Q_LMEAE; }#endif QBA break;#endif DW750 || DW730 || QBA }}#ifdef QBA/* * Determine the interrupt priority of a Q-bus * peripheral. The device probe routine must spl6(), * attempt to make the device request an interrupt, * delaying as necessary, then call this routine * before resetting the device. */qbgetpri(){ int pri; extern int cvec; for (pri = 0x17; pri > 0x14; ) { if (cvec && cvec != 0x200) /* interrupted at pri */ break; pri--; splx(pri - 1); } (void) spl0(); return (pri);}#endif#ifdef DW780int ubawedgecnt = 10;int ubacrazy = 500;int zvcnt_max = 5000; /* in 8 sec *//* * This routine is called by the locore code to process a UBA * error on an 11/780 or 8600. 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, ipl, uvec, uba) register int uban; register struct uba_hd *uh; int ipl, uvec; register struct uba_regs *uba;{ register sr, s; if (uvec == 0) { /* * Declare dt as unsigned so that negative values * are handled as >8 below, in case time was set back. */ u_long dt = time.tv_sec - uh->uh_zvtime; uh->uh_zvtotal++; if (dt > 8) { uh->uh_zvtime = time.tv_sec; uh->uh_zvcnt = 0; } if (++uh->uh_zvcnt > zvcnt_max) { printf("uba%d: too many zero vectors (%d in <%d sec)\n", uban, uh->uh_zvcnt, dt + 1); printf("\tIPL 0x%x\n\tcnfgr: %b Adapter Code: 0x%x\n", ipl, uba->uba_cnfgr&(~0xff), UBACNFGR_BITS, uba->uba_cnfgr&0xff); printf("\tsr: %b\n\tdcr: %x (MIC %sOK)\n", uba->uba_sr, ubasr_bits, uba->uba_dcr, (uba->uba_dcr&0x8000000)?"":"NOT "); ubareset(uban); } return; } if (uba->uba_cnfgr & NEX_CFGFLT) { printf("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 = spluba(); printf("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;}#endif/* * Look for devices with unibus memory, allow them to configure, then disable * map registers as necessary. Called during autoconfiguration and ubareset. * The device ubamem routine returns 0 on success, 1 on success if it is fully * configured (has no csr or interrupt, so doesn't need to be probed), * and -1 on failure. */ubameminit(uban){ register struct uba_device *ui; register struct uba_hd *uh = &uba_hd[uban]; caddr_t umembase = umem[uban] + 0x3e000, addr;#define ubaoff(off) ((int)(off) & 0x1fff) uh->uh_lastmem = 0; for (ui = ubdinit; ui->ui_driver; ui++) { if (ui->ui_ubanum != uban && ui->ui_ubanum != '?') continue; if (ui->ui_driver->ud_ubamem) { /* * During autoconfiguration, need to fudge ui_addr. */ addr = ui->ui_addr; ui->ui_addr = umembase + ubaoff(addr); switch ((*ui->ui_driver->ud_ubamem)(ui, uban)) { case 1: ui->ui_alive = 1; /* FALLTHROUGH */ case 0: ui->ui_ubanum = uban; break; } ui->ui_addr = addr; } }#ifdef DW780 /* * On a DW780, throw away any map registers disabled by rounding * the map disable in the configuration register * up to the next 8K boundary, or below the last unibus memory. */ if (uh->uh_type == DW780) { register i; i = btop(((uh->uh_lastmem + 8191) / 8192) * 8192); while (i) (void) rmget(uh->uh_map, 1, i--); }#endif}/* * 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. * On a DW780, should only be called from ubameminit, or in ascending order * from 0 with 8K-sized and -aligned addresses; freeing memory that isn't * the last unibus memory would free unusable map registers. * Doalloc is 1 to allocate, 0 to deallocate. */ubamem(uban, addr, npg, doalloc) int uban, addr, npg, doalloc;{ register struct uba_hd *uh = &uba_hd[uban]; register int a; int s; a = (addr >> 9) + 1; s = spluba(); if (doalloc) a = rmget(uh->uh_map, npg, a); else rmfree(uh->uh_map, (long)npg, (long)a); splx(s); if (a) { register int i, *m; m = (int *)&uh->uh_mr[a - 1]; for (i = 0; i < npg; i++) *m++ = 0; /* All off, especially 'valid' */ i = addr + npg * 512; if (doalloc && i > uh->uh_lastmem) uh->uh_lastmem = i; else if (doalloc == 0 && i == uh->uh_lastmem) uh->uh_lastmem = addr;#ifdef DW780 /* * On a 780, set up the map register disable * field in the configuration register. Beware * of callers that request memory ``out of order'' * or in sections other than 8K multiples. * Ubameminit handles such requests properly, however. */ if (uh->uh_type == DW780) { i = uh->uh_uba->uba_cr &~ 0x7c000000; i |= ((uh->uh_lastmem + 8191) / 8192) << 26; uh->uh_uba->uba_cr = i; }#endif } return (a);}#include "ik.h"#include "vs.h"#if NIK > 0 || NVS > 0/* * Map a virtual address into users address space. Actually all we * do is turn on the user mode write protection bits for the particular * page of memory involved. */maptouser(vaddress) caddr_t vaddress;{ kvtopte(vaddress)->pg_prot = (PG_UW >> 27);}unmaptouser(vaddress) caddr_t vaddress;{ kvtopte(vaddress)->pg_prot = (PG_KW >> 27);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -