#include "sys/param.h" #include "sys/dir.h" #include "sys/user.h" #include "sys/uba.h" #include "sys/map.h" #include "sys/buf.h" #include "sys/page.h" struct map ubmap[UAMSIZ]; struct map bdpmap[15]; int ubazero; static char bdpwant, ubmwant; paddr_t ubcoffs; extern _sdata, end; ubmalloc(size, bdpflg) unsigned size; { /* * Allocate as many contiguous UBA mapping registers * as are necessary to do transfer of 'size' bytes. * Wait for enough map registers. * if 'bdpflg' is non-zero: a buffered data path (BDP) is used; * else a direct data path (DDP). * Return * |21 - - 18|17 - - 9|8 - - 0| * | BDP # | # | start | * | | map reg | map reg | */ register nseg, base; register bdp = 0; nseg = btoc(size) + 2; spl6(); while ((base = malloc(ubmap, nseg)) == NULL) { ubmwant++; sleep(ubmap, PSWP); } if (bdpflg) while ( (bdp=malloc(bdpmap, 1)) == NULL) { bdpwant++; sleep(bdpmap, PSWP); } spl0(); return((bdp<<18) | (nseg<<9) | base); } ubmfree(umd) { register nseg, base, bdp; spl6(); bdp = (umd>>18) & 0x0f; if (bdp) { ubavad.uba_dpr[bdp] |= BNE; /* purge */ mfree(bdpmap, 1, bdp); if (bdpwant) { bdpwant = 0; wakeup(bdpmap); } } nseg = (umd>>9) & 0x1ff; base = (umd) & 0x1ff; mfree(ubmap, nseg, base); if (ubmwant) { ubmwant = 0; wakeup(ubmap); } spl0(); } ubainit() { register n; n = (((int)(&end)) - ((int)(&_sdata)) + 0x1ff) >> 9; ubaclr(); mfree(ubmap, 496-n, n); mfree(bdpmap, 15, 1); ubcoffs = (int)(&_sdata) & ~0x1ff; } paddr_t ubmaddr(bp, umd) register struct buf *bp; { register base, nseg; register bdp, pfn; int count; extern mbautl[], Mbamap[]; pfn = 0; if (bdp = ((umd>>18) & 0xf)) { ubavad.uba_dpr[bdp] |= BNE; if (paddr(bp) & 01) pfn |= BO; } pfn |= MRV | bdp << 21; nseg = (umd>>9) & 0x1ff; count = btoc(bp->b_bcount + (paddr(bp)&0x1ff)); if (count<nseg) nseg = count; base = umd & 0x1ff; if (bp->b_flags&B_PHYS) { register *pt, *io; register pf; ptaccess(bp->b_proc, Mbamap, mbautl); io = &ubavad.uba_map[base]; pf = paddr(bp)>>9; if (pf & 0x200000) { /* I/O to stack */ pf += ((struct user *)mbautl)->u_pcb.pcb_szpt*128 - 0x400000; } pt = mbautl + UPAGES*128 + pf; while (--nseg >= 0) if ((*io++ = ((*pt++ & 0x1ffff) | pfn)) == pfn) panic("uba, zero entry"); *io = 0; return((base<<9)|(paddr(bp)&0x1fe)); } else { return(paddr(bp) - ubcoffs); } } ubasrv(vec) { if (vec==0) { ubazero++; return; } if (ubavad.uba_cnfgr&CFGFLT) { printf("UBA SBI fault %x %x\n", ubavad.uba_cnfgr, ubavad.uba_sr); return; } printf("UBA status %x, fubar %o\n", ubavad.uba_sr, ubavad.uba_fubar<<2); ubavad.uba_sr = ubavad.uba_sr; /* possible normal interrupt here ? */ } ubastray(vec) { printf("stray UBA interrupt at %o\n",vec); } ubaclr() { register base, i, n; base = (((int)(&_sdata)) >> 9) & PG_PFNUM; n = (((int)(&end)) - ((int)(&_sdata)) + 0x1ff) >> 9; for ( i=0; i<n; i++) { ubavad.uba_map[i] = MRV | base++; } }