| 1 | /* uba.c 3.6 %G% */ |
| 2 | |
| 3 | #include "../h/param.h" |
| 4 | #include "../h/map.h" |
| 5 | #include "../h/pte.h" |
| 6 | #include "../h/uba.h" |
| 7 | #include "../h/buf.h" |
| 8 | #include "../h/dir.h" |
| 9 | #include "../h/user.h" |
| 10 | #include "../h/proc.h" |
| 11 | #include "../h/vm.h" |
| 12 | #include "../h/conf.h" |
| 13 | |
| 14 | /* |
| 15 | * Allocate as many contiguous UBA mapping registers |
| 16 | * as are necessary to do transfer of bcnt bytes |
| 17 | * to/from location baddr. Wait for enough map registers. |
| 18 | * |
| 19 | * Bdpflg is non-zero if a "buffered data path" (BDP) is |
| 20 | * to be used, else 0 -> use direct data path (DDP). Return |
| 21 | * |
| 22 | * Bits 0-8 Byte offset |
| 23 | * Bits 9-17 Start map reg. no. |
| 24 | * Bits 18-27 No. mapping reg's |
| 25 | * Bits 28-31 BDP no. |
| 26 | */ |
| 27 | ubasetup(bp, bdpflg) |
| 28 | struct buf *bp; |
| 29 | { |
| 30 | register int temp, i; |
| 31 | int npf, reg, bdp; |
| 32 | unsigned v; |
| 33 | register struct pte *pte, *io; |
| 34 | struct proc *rp; |
| 35 | int a, o, ubinfo; |
| 36 | |
| 37 | v = btop(bp->b_un.b_addr); |
| 38 | o = (int)bp->b_un.b_addr & PGOFSET; |
| 39 | npf = btoc(bp->b_bcount + o) + 1; |
| 40 | a = spl6(); |
| 41 | while ((reg = malloc(ubamap, npf)) == 0) { |
| 42 | panic("ran out of uba map"); |
| 43 | umrwant++; |
| 44 | sleep((caddr_t)ubamap, PSWP); |
| 45 | } |
| 46 | reg--; |
| 47 | bdp = 0; |
| 48 | if (bdpflg) |
| 49 | while ((bdp = malloc(bdpmap, 1)) == 0) { |
| 50 | panic("ran out of bdp's"); |
| 51 | bdpwant++; |
| 52 | sleep((caddr_t)bdpmap, PSWP); |
| 53 | } |
| 54 | splx(a); |
| 55 | ubinfo = (bdp << 28) | (npf << 18) | (reg << 9) | o; |
| 56 | io = &(((struct uba_regs *)UBA0)->uba_map[reg]); |
| 57 | temp = (bdp << 21) | MRV; |
| 58 | rp = bp->b_flags&B_DIRTY ? &proc[2] : bp->b_proc; |
| 59 | if (bdp && (o & 01)) |
| 60 | temp |= BO; |
| 61 | if (bp->b_flags & B_UAREA) { |
| 62 | for (i = UPAGES - bp->b_bcount / NBPG; i < UPAGES; i++) { |
| 63 | if (rp->p_addr[i].pg_pfnum == 0) |
| 64 | panic("uba: zero upage"); |
| 65 | *(int *)io++ = rp->p_addr[i].pg_pfnum | temp; |
| 66 | } |
| 67 | } else if ((bp->b_flags & B_PHYS) == 0) { |
| 68 | pte = &Sysmap[btop(((int)bp->b_un.b_addr)&0x7fffffff)]; |
| 69 | while (--npf != 0) |
| 70 | *(int *)io++ = pte++->pg_pfnum | temp; |
| 71 | } else { |
| 72 | if (bp->b_flags & B_PAGET) |
| 73 | pte = &Usrptmap[btokmx((struct pte *)bp->b_un.b_addr)]; |
| 74 | else |
| 75 | pte = vtopte(rp, v); |
| 76 | while (--npf != 0) { |
| 77 | if (pte->pg_pfnum == 0) |
| 78 | panic("uba zero uentry"); |
| 79 | *(int *)io++ = pte++->pg_pfnum | temp; |
| 80 | } |
| 81 | } |
| 82 | *(int *)io++ = 0; |
| 83 | return (ubinfo); |
| 84 | } |
| 85 | |
| 86 | /* |
| 87 | * Non buffer unibus interface... set up a buffer and call ubasetup. |
| 88 | */ |
| 89 | uballoc(addr, bcnt, bdpflg) |
| 90 | caddr_t addr; |
| 91 | unsigned short bcnt; |
| 92 | { |
| 93 | struct buf ubabuf; |
| 94 | |
| 95 | ubabuf.b_un.b_addr = addr; |
| 96 | ubabuf.b_flags = B_BUSY; |
| 97 | ubabuf.b_bcount = bcnt; |
| 98 | /* that's all the fields ubasetup() needs */ |
| 99 | return (ubasetup(&ubabuf, bdpflg)); |
| 100 | } |
| 101 | |
| 102 | ubafree(mr) |
| 103 | int mr; |
| 104 | { |
| 105 | register int bdp, reg, npf, a; |
| 106 | |
| 107 | a = spl6(); |
| 108 | bdp = (mr >> 28) & 0x0f; |
| 109 | if (bdp) { |
| 110 | ((struct uba_regs *)UBA0)->uba_dpr[bdp] |= BNE; /* purge */ |
| 111 | mfree(bdpmap, 1, bdp); |
| 112 | if (bdpwant) { |
| 113 | bdpwant = 0; |
| 114 | wakeup((caddr_t)bdpmap); |
| 115 | } |
| 116 | } |
| 117 | npf = (mr >> 18) & 0x3ff; |
| 118 | reg = ((mr >> 9) & 0x1ff) + 1; |
| 119 | mfree(ubamap, npf, reg); |
| 120 | if (umrwant) { |
| 121 | umrwant = 0; |
| 122 | wakeup((caddr_t)ubamap); |
| 123 | } |
| 124 | splx(a); |
| 125 | } |
| 126 | |
| 127 | ubainit() |
| 128 | { |
| 129 | |
| 130 | mfree(ubamap, 496, 1); |
| 131 | mfree(bdpmap, 15, 1); |
| 132 | } |
| 133 | |
| 134 | #define DELAY(N) { register int d; d = N; while (--d > 0); } |
| 135 | |
| 136 | ubareset() |
| 137 | { |
| 138 | struct uba_regs *up = (struct uba_regs *)UBA0; |
| 139 | register struct cdevsw *cdp; |
| 140 | int i, s; |
| 141 | |
| 142 | s = spl6(); |
| 143 | printf("UBA RESET:"); |
| 144 | up->uba_cr = ADINIT; |
| 145 | up->uba_cr = IFS|BRIE|USEFIE|SUEFIE; |
| 146 | while ((up->uba_cnfgr & UBIC) == 0) |
| 147 | ; |
| 148 | for (cdp = cdevsw; cdp->d_open; cdp++) |
| 149 | (*cdp->d_reset)(); |
| 150 | printf("\n"); |
| 151 | splx(s); |
| 152 | } |