X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/0468e5fac684d03667a96b5be6f000bf1aba758d..176c481f62876316668544ff7b26e7956a4243de:/usr/src/sys/vax/if/if_uba.c diff --git a/usr/src/sys/vax/if/if_uba.c b/usr/src/sys/vax/if/if_uba.c index 6396e92714..c9298a25d0 100644 --- a/usr/src/sys/vax/if/if_uba.c +++ b/usr/src/sys/vax/if/if_uba.c @@ -1,14 +1,20 @@ -/* if_uba.c 4.1 81/11/25 */ +/* if_uba.c 4.11 82/05/19 */ #include "../h/param.h" #include "../h/systm.h" #include "../h/mbuf.h" #include "../h/map.h" #include "../h/pte.h" +#include "../h/buf.h" #include "../h/ubareg.h" #include "../h/ubavar.h" #include "../h/cmap.h" #include "../h/mtpr.h" +#include "../h/vmmac.h" +#include "../h/socket.h" +#include "../net/in.h" +#include "../net/in_systm.h" +#include "../net/if.h" #include "../net/if_uba.h" /* @@ -29,138 +35,127 @@ if_ubainit(ifu, uban, hlen, nmr) register struct ifuba *ifu; int uban, hlen, nmr; { - register caddr_t cp = m_pgalloc(2 * (nmr + 1)); + register caddr_t cp; + int i, ncl; - if (cp == 0) - return (0); - ifu->if_uban = uban; - ifu->if_uba = &uba_hd[uban]->uh_uba; - ifu->if_r.if_addr = cp + NMBPG - hlen; - ifu->if_w.if_addr = ifu->if_r.if_addr + (nmr + 1) * NMBPG; - if (if_ubaalloc(ifu, &ifu->if_r) == 0) +COUNT(IF_UBAINIT); + ncl = clrnd(nmr + CLSIZE) / CLSIZE; + if (ifu->ifu_r.ifrw_addr) + cp = ifu->ifu_r.ifrw_addr - (CLBYTES - hlen); + else { + cp = m_clalloc(2 * ncl, MPG_SPACE); + if (cp == 0) + return (0); + ifu->ifu_r.ifrw_addr = cp + CLBYTES - hlen; + ifu->ifu_w.ifrw_addr = ifu->ifu_r.ifrw_addr + ncl * CLBYTES; + ifu->ifu_hlen = hlen; + ifu->ifu_uban = uban; + ifu->ifu_uba = uba_hd[uban].uh_uba; + } + if (if_ubaalloc(ifu, &ifu->ifu_r, nmr) == 0) goto bad; - if (if_ubaalloc(ifu, &ifu->if_w) == 0) + if (if_ubaalloc(ifu, &ifu->ifu_w, nmr) == 0) goto bad2; - for (i = 0; i < IF_NUBAMR; i++) - ifu->if_xmap[i] = ifu->if_w.if_map[i+1]; - ifu->if_xswapd = 0; + for (i = 0; i < nmr; i++) + ifu->ifu_wmap[i] = ifu->ifu_w.ifrw_mr[i]; + ifu->ifu_xswapd = 0; return (1); bad2: - ubafree(ifu->ifu_uban, ifu->if_r.ifrw_info); + ubarelse(ifu->ifu_uban, &ifu->ifu_r.ifrw_info); bad: - m_pgfree(cp, 2 * (nmr + 1)); + m_pgfree(cp, 2 * ncl); + ifu->ifu_r.ifrw_addr = 0; return (0); } /* * Setup either a ifrw structure by allocating UNIBUS map registers, - * a buffered data path, and initializing the fields of the ifrw structure - * to minimize run-time overhead. + * possibly a buffered data path, and initializing the fields of + * the ifrw structure to minimize run-time overhead. */ static -if_ubaalloc(ifu, ifrw) +if_ubaalloc(ifu, ifrw, nmr) struct ifuba *ifu; register struct ifrw *ifrw; + int nmr; { register int info; +COUNT(IF_UBAALLOC); info = - uballoc(ifu->ifu_uban, ifrw->ifrw_addr, IF_NUBAMR*NMBPG + hlen, - UBA_NEED16|UBA_NEEDBDP); + uballoc(ifu->ifu_uban, ifrw->ifrw_addr, nmr*NBPG + ifu->ifu_hlen, + ifu->ifu_flags); if (info == 0) - goto bad; + return (0); ifrw->ifrw_info = info; ifrw->ifrw_bdp = UBAI_BDP(info); - ifrw->ifrw_proto = UBAMR_MRV | UBAI_DPDF(info); - ifrw->ifrw_mr = &ifu->if_uba[UBAI_MR(info) + 1]; + ifrw->ifrw_proto = UBAMR_MRV | (UBAI_BDP(info) << UBAMR_DPSHIFT); + ifrw->ifrw_mr = &ifu->ifu_uba->uba_map[UBAI_MR(info) + 1]; + return (1); } /* - * Pull read data off a interface, given length. - * Map the header into a mbuf, and then copy or - * remap the data into a chain of mbufs. - * Return 0 if there is no space, or a pointer - * to the assembled mbuf chain. + * Pull read data off a interface. + * Len is length of data, with local net header stripped. + * Off is non-zero if a trailer protocol was used, and + * gives the offset of the trailer information. + * We copy the trailer information and then all the normal + * data into mbufs. When full cluster sized units are present + * on the interface on cluster boundaries we can get them more + * easily by remapping, and take advantage of this here. */ struct mbuf * -if_rubaget(ifu, len) +if_rubaget(ifu, totlen, off0) register struct ifuba *ifu; - int len; + int totlen, off0; { - register struct mbuf *m; - register caddr_t cp; - struct mbuf *mp, *p, *top; + struct mbuf *top, **mp, *m; + int off = off0, len; + register caddr_t cp = ifu->ifu_r.ifrw_addr + ifu->ifu_hlen; - /* - * First pull local net header off into a mbuf. - */ - MGET(m, 0); - if (m == 0) - return (0); - m->m_off = MMINOFF; - m->m_len = ifu->if_hlen; - top = m; - cp = ifu->ifu_r.ifrw_addr; - bcopy(cp, mtod(m, caddr_t), ifu->if_hlen); - len -= hlen; - cp += hlen; +COUNT(IF_RUBAGET); - /* - * Now pull data off. If whole pages - * are there, pull into pages if possible, - * otherwise copy small blocks into mbufs. - */ - mp = m; - while (len > 0) { + top = 0; + mp = ⊤ + while (totlen > 0) { MGET(m, 0); if (m == 0) - goto flush; - if (len >= CLSIZE) { + goto bad; + if (off) { + len = totlen - off; + cp = ifu->ifu_r.ifrw_addr + ifu->ifu_hlen + off; + } else + len = totlen; + if (len >= CLBYTES) { + struct mbuf *p; struct pte *cpte, *ppte; - int i, x, *ip; + int x, *ip, i; MCLGET(p, 1); if (p == 0) goto nopage; - m->m_len = CLSIZE; + len = m->m_len = CLBYTES; m->m_off = (int)p - (int)m; - if ((int)cp & CLOFF) + if (!claligned(cp)) goto copy; /* - * Cluster size data on cluster size boundary. - * Input by remapping newly allocated pages to - * UNIBUS, and taking pages with data already - * in them. - * - * Cpte is the pte of the virtual memory which - * is mapped to the UNIBUS, and ppte is the pte - * for the fresh pages. We switch the memory - * copies of these pte's, to make the allocated - * virtual memory contain the data (using the old - * physical pages). We have to rewrite - * the UNIBUS map so that the newly allocated - * pages will be used for the next UNIBUS read, - * and invalidate the kernel translations - * for the virtual addresses of the pages - * we are flipping. - * - * The idea here is that this is supposed - * to take less time than copying the data. + * Switch pages mapped to UNIBUS with new page p, + * as quick form of copy. Remap UNIBUS and invalidate. */ - cpte = &Mbmap[mtocl(cp)]; - ppte = &Mbmap[mtocl(p)]; - x = btop(cp - ifu->if_r.ifrw_addr); - ip = (int *)&ifu->ifu_r.ifrw_mr[x+1]; + cpte = &Mbmap[mtocl(cp)*CLSIZE]; + ppte = &Mbmap[mtocl(p)*CLSIZE]; + x = btop(cp - ifu->ifu_r.ifrw_addr); + ip = (int *)&ifu->ifu_r.ifrw_mr[x]; for (i = 0; i < CLSIZE; i++) { struct pte t; - t = *ppte; *ppte = *cpte; *cpte = t; + t = *ppte; *ppte++ = *cpte; *cpte = t; *ip++ = - *cpte++->pg_pfnum|ifu->if_r.ifrw_proto; + cpte++->pg_pfnum|ifu->ifu_r.ifrw_proto; mtpr(TBIS, cp); - cp += NMBPG; + cp += NBPG; mtpr(TBIS, (caddr_t)p); - p += NMBPG / sizeof (*p); + p += NBPG / sizeof (*p); } goto nocopy; } @@ -171,9 +166,18 @@ copy: bcopy(cp, mtod(m, caddr_t), (unsigned)m->m_len); cp += m->m_len; nocopy: - len -= m->m_len; - mp->m_next = m; - mp = m; + *mp = m; + mp = &m->m_next; + if (off) { + /* sort of an ALGOL-W style for statement... */ + off += m->m_len; + if (off == totlen) { + cp = ifu->ifu_r.ifrw_addr + ifu->ifu_hlen; + off = 0; + totlen = off0; + } + } else + totlen -= m->m_len; } return (top); bad: @@ -195,37 +199,56 @@ if_wubaput(ifu, m) register struct mbuf *mp; register caddr_t cp, dp; register int i; - int xswapd = ifu->ifu_xswapd; - int x; + int xswapd = 0; + int x, cc; - ifu->ifu_xswapd = 0; +COUNT(IF_WUBAPUT); cp = ifu->ifu_w.ifrw_addr; while (m) { dp = mtod(m, char *); - if (claligned(cp) && claligned(dp)) { + if (claligned(cp) && claligned(dp) && m->m_len == CLBYTES) { struct pte *pte; int *ip; - pte = &Mbmap[mtocl(dp)]; + pte = &Mbmap[mtocl(dp)*CLSIZE]; x = btop(cp - ifu->ifu_w.ifrw_addr); - ip = &ifu->ifu_w.ifrw_mr[x + 1]; + ip = (int *)&ifu->ifu_w.ifrw_mr[x]; for (i = 0; i < CLSIZE; i++) *ip++ = ifu->ifu_w.ifrw_proto | pte++->pg_pfnum; - ifu->ifu_xswapd |= 1 << (x>>CLSHIFT); - } else + xswapd |= 1 << (x>>(CLSHIFT-PGSHIFT)); + mp = m->m_next; + m->m_next = ifu->ifu_xtofree; + ifu->ifu_xtofree = m; + cp += m->m_len; + } else { bcopy(mtod(m, caddr_t), cp, (unsigned)m->m_len); - cp += m->m_len; - MFREE(m, mp); /* XXX too soon! */ + cp += m->m_len; + MFREE(m, mp); + } m = mp; } + + /* + * Xswapd is the set of clusters we just mapped out. Ifu->ifu_xswapd + * is the set of clusters mapped out from before. We compute + * the number of clusters involved in this operation in x. + * Clusters mapped out before and involved in this operation + * should be unmapped so original pages will be accessed by the device. + */ + cc = cp - ifu->ifu_w.ifrw_addr; + x = ((cc - ifu->ifu_hlen) + CLBYTES - 1) >> CLSHIFT; + ifu->ifu_xswapd &= ~xswapd; xswapd &= ~ifu->ifu_xswapd; - if (xswapd) - while (i = ffs(xswapd)) { - i--; - xswapd &= ~(1<ifu_rw.ifrw_mr[i] = ifu->ifu_xmap[i]; - i++; - } + while (i = ffs(ifu->ifu_xswapd)) { + i--; + if (i >= x) + break; + ifu->ifu_xswapd &= ~(1<ifu_w.ifrw_mr[i] = ifu->ifu_wmap[i]; + i++; } + } + ifu->ifu_xswapd |= xswapd; + return (cc); }