|
|
1.1 ! root 1: /* if_uba.c 6.1 83/07/29 */ ! 2: ! 3: #include "../machine/pte.h" ! 4: ! 5: #include "../h/param.h" ! 6: #include "../h/systm.h" ! 7: #include "../h/mbuf.h" ! 8: #include "../h/map.h" ! 9: #include "../h/buf.h" ! 10: #include "../h/cmap.h" ! 11: #include "../h/vmmac.h" ! 12: #include "../h/socket.h" ! 13: ! 14: #include "../net/if.h" ! 15: ! 16: #include "../vax/mtpr.h" ! 17: #include "../vaxif/if_uba.h" ! 18: #include "../vaxuba/ubareg.h" ! 19: #include "../vaxuba/ubavar.h" ! 20: ! 21: /* ! 22: * Routines supporting UNIBUS network interfaces. ! 23: * ! 24: * TODO: ! 25: * Support interfaces using only one BDP statically. ! 26: */ ! 27: ! 28: /* ! 29: * Init UNIBUS for interface on uban whose headers of size hlen are to ! 30: * end on a page boundary. We allocate a UNIBUS map register for the page ! 31: * with the header, and nmr more UNIBUS map registers for i/o on the adapter, ! 32: * doing this twice: once for reading and once for writing. We also ! 33: * allocate page frames in the mbuffer pool for these pages. ! 34: */ ! 35: if_ubainit(ifu, uban, hlen, nmr) ! 36: register struct ifuba *ifu; ! 37: int uban, hlen, nmr; ! 38: { ! 39: register caddr_t cp; ! 40: int i, ncl; ! 41: ! 42: ncl = clrnd(nmr + CLSIZE) / CLSIZE; ! 43: if (ifu->ifu_r.ifrw_addr) ! 44: cp = ifu->ifu_r.ifrw_addr - (CLBYTES - hlen); ! 45: else { ! 46: cp = m_clalloc(2 * ncl, MPG_SPACE); ! 47: if (cp == 0) ! 48: return (0); ! 49: ifu->ifu_r.ifrw_addr = cp + CLBYTES - hlen; ! 50: ifu->ifu_w.ifrw_addr = ifu->ifu_r.ifrw_addr + ncl * CLBYTES; ! 51: ifu->ifu_hlen = hlen; ! 52: ifu->ifu_uban = uban; ! 53: ifu->ifu_uba = uba_hd[uban].uh_uba; ! 54: } ! 55: if (if_ubaalloc(ifu, &ifu->ifu_r, nmr) == 0) ! 56: goto bad; ! 57: if (if_ubaalloc(ifu, &ifu->ifu_w, nmr) == 0) ! 58: goto bad2; ! 59: for (i = 0; i < nmr; i++) ! 60: ifu->ifu_wmap[i] = ifu->ifu_w.ifrw_mr[i]; ! 61: ifu->ifu_xswapd = 0; ! 62: return (1); ! 63: bad2: ! 64: ubarelse(ifu->ifu_uban, &ifu->ifu_r.ifrw_info); ! 65: bad: ! 66: m_pgfree(cp, 2 * ncl); ! 67: ifu->ifu_r.ifrw_addr = 0; ! 68: return (0); ! 69: } ! 70: ! 71: /* ! 72: * Setup either a ifrw structure by allocating UNIBUS map registers, ! 73: * possibly a buffered data path, and initializing the fields of ! 74: * the ifrw structure to minimize run-time overhead. ! 75: */ ! 76: static ! 77: if_ubaalloc(ifu, ifrw, nmr) ! 78: struct ifuba *ifu; ! 79: register struct ifrw *ifrw; ! 80: int nmr; ! 81: { ! 82: register int info; ! 83: ! 84: info = ! 85: uballoc(ifu->ifu_uban, ifrw->ifrw_addr, nmr*NBPG + ifu->ifu_hlen, ! 86: ifu->ifu_flags); ! 87: if (info == 0) ! 88: return (0); ! 89: ifrw->ifrw_info = info; ! 90: ifrw->ifrw_bdp = UBAI_BDP(info); ! 91: ifrw->ifrw_proto = UBAMR_MRV | (UBAI_BDP(info) << UBAMR_DPSHIFT); ! 92: ifrw->ifrw_mr = &ifu->ifu_uba->uba_map[UBAI_MR(info) + 1]; ! 93: return (1); ! 94: } ! 95: ! 96: /* ! 97: * Pull read data off a interface. ! 98: * Len is length of data, with local net header stripped. ! 99: * Off is non-zero if a trailer protocol was used, and ! 100: * gives the offset of the trailer information. ! 101: * We copy the trailer information and then all the normal ! 102: * data into mbufs. When full cluster sized units are present ! 103: * on the interface on cluster boundaries we can get them more ! 104: * easily by remapping, and take advantage of this here. ! 105: */ ! 106: struct mbuf * ! 107: if_rubaget(ifu, totlen, off0) ! 108: register struct ifuba *ifu; ! 109: int totlen, off0; ! 110: { ! 111: struct mbuf *top, **mp, *m; ! 112: int off = off0, len; ! 113: register caddr_t cp = ifu->ifu_r.ifrw_addr + ifu->ifu_hlen; ! 114: ! 115: ! 116: top = 0; ! 117: mp = ⊤ ! 118: while (totlen > 0) { ! 119: MGET(m, M_DONTWAIT, MT_DATA); ! 120: if (m == 0) ! 121: goto bad; ! 122: if (off) { ! 123: len = totlen - off; ! 124: cp = ifu->ifu_r.ifrw_addr + ifu->ifu_hlen + off; ! 125: } else ! 126: len = totlen; ! 127: if (len >= CLBYTES) { ! 128: struct mbuf *p; ! 129: struct pte *cpte, *ppte; ! 130: int x, *ip, i; ! 131: ! 132: MCLGET(p, 1); ! 133: if (p == 0) ! 134: goto nopage; ! 135: len = m->m_len = CLBYTES; ! 136: m->m_off = (int)p - (int)m; ! 137: if (!claligned(cp)) ! 138: goto copy; ! 139: ! 140: /* ! 141: * Switch pages mapped to UNIBUS with new page p, ! 142: * as quick form of copy. Remap UNIBUS and invalidate. ! 143: */ ! 144: cpte = &Mbmap[mtocl(cp)*CLSIZE]; ! 145: ppte = &Mbmap[mtocl(p)*CLSIZE]; ! 146: x = btop(cp - ifu->ifu_r.ifrw_addr); ! 147: ip = (int *)&ifu->ifu_r.ifrw_mr[x]; ! 148: for (i = 0; i < CLSIZE; i++) { ! 149: struct pte t; ! 150: t = *ppte; *ppte++ = *cpte; *cpte = t; ! 151: *ip++ = ! 152: cpte++->pg_pfnum|ifu->ifu_r.ifrw_proto; ! 153: mtpr(TBIS, cp); ! 154: cp += NBPG; ! 155: mtpr(TBIS, (caddr_t)p); ! 156: p += NBPG / sizeof (*p); ! 157: } ! 158: goto nocopy; ! 159: } ! 160: nopage: ! 161: m->m_len = MIN(MLEN, len); ! 162: m->m_off = MMINOFF; ! 163: copy: ! 164: bcopy(cp, mtod(m, caddr_t), (unsigned)m->m_len); ! 165: cp += m->m_len; ! 166: nocopy: ! 167: *mp = m; ! 168: mp = &m->m_next; ! 169: if (off) { ! 170: /* sort of an ALGOL-W style for statement... */ ! 171: off += m->m_len; ! 172: if (off == totlen) { ! 173: cp = ifu->ifu_r.ifrw_addr + ifu->ifu_hlen; ! 174: off = 0; ! 175: totlen = off0; ! 176: } ! 177: } else ! 178: totlen -= m->m_len; ! 179: } ! 180: return (top); ! 181: bad: ! 182: m_freem(top); ! 183: return (0); ! 184: } ! 185: ! 186: /* ! 187: * Map a chain of mbufs onto a network interface ! 188: * in preparation for an i/o operation. ! 189: * The argument chain of mbufs includes the local network ! 190: * header which is copied to be in the mapped, aligned ! 191: * i/o space. ! 192: */ ! 193: if_wubaput(ifu, m) ! 194: register struct ifuba *ifu; ! 195: register struct mbuf *m; ! 196: { ! 197: register struct mbuf *mp; ! 198: register caddr_t cp, dp; ! 199: register int i; ! 200: int xswapd = 0; ! 201: int x, cc; ! 202: ! 203: cp = ifu->ifu_w.ifrw_addr; ! 204: while (m) { ! 205: dp = mtod(m, char *); ! 206: if (claligned(cp) && claligned(dp) && m->m_len == CLBYTES) { ! 207: struct pte *pte; int *ip; ! 208: pte = &Mbmap[mtocl(dp)*CLSIZE]; ! 209: x = btop(cp - ifu->ifu_w.ifrw_addr); ! 210: ip = (int *)&ifu->ifu_w.ifrw_mr[x]; ! 211: for (i = 0; i < CLSIZE; i++) ! 212: *ip++ = ! 213: ifu->ifu_w.ifrw_proto | pte++->pg_pfnum; ! 214: xswapd |= 1 << (x>>(CLSHIFT-PGSHIFT)); ! 215: mp = m->m_next; ! 216: m->m_next = ifu->ifu_xtofree; ! 217: ifu->ifu_xtofree = m; ! 218: cp += m->m_len; ! 219: } else { ! 220: bcopy(mtod(m, caddr_t), cp, (unsigned)m->m_len); ! 221: cp += m->m_len; ! 222: MFREE(m, mp); ! 223: } ! 224: m = mp; ! 225: } ! 226: ! 227: /* ! 228: * Xswapd is the set of clusters we just mapped out. Ifu->ifu_xswapd ! 229: * is the set of clusters mapped out from before. We compute ! 230: * the number of clusters involved in this operation in x. ! 231: * Clusters mapped out before and involved in this operation ! 232: * should be unmapped so original pages will be accessed by the device. ! 233: */ ! 234: cc = cp - ifu->ifu_w.ifrw_addr; ! 235: x = ((cc - ifu->ifu_hlen) + CLBYTES - 1) >> CLSHIFT; ! 236: ifu->ifu_xswapd &= ~xswapd; ! 237: xswapd &= ~ifu->ifu_xswapd; ! 238: while (i = ffs(ifu->ifu_xswapd)) { ! 239: i--; ! 240: if (i >= x) ! 241: break; ! 242: ifu->ifu_xswapd &= ~(1<<i); ! 243: i *= CLSIZE; ! 244: for (x = 0; x < CLSIZE; x++) { ! 245: ifu->ifu_w.ifrw_mr[i] = ifu->ifu_wmap[i]; ! 246: i++; ! 247: } ! 248: } ! 249: ifu->ifu_xswapd |= xswapd; ! 250: return (cc); ! 251: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.