/*
- * Copyright (c) 1982, 1986 Regents of the University of California.
- * All rights reserved. The Berkeley software License Agreement
- * specifies the terms and conditions for redistribution.
+ * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
+ * All rights reserved.
*
- * @(#)if_uba.c 7.9 (Berkeley) 5/24/88
+ * Redistribution is only permitted until one year after the first shipment
+ * of 4.4BSD by the Regents. Otherwise, redistribution and use in source and
+ * binary forms are permitted provided that: (1) source distributions retain
+ * this entire copyright notice and comment, and (2) distributions including
+ * binaries display the following acknowledgement: This product includes
+ * software developed by the University of California, Berkeley and its
+ * contributors'' in the documentation or other materials provided with the
+ * distribution and in all advertising materials mentioning features or use
+ * of this software. Neither the name of the University nor the names of
+ * its contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * @(#)if_uba.c 7.15 (Berkeley) 6/28/90
*/
#include "param.h"
#include "systm.h"
+#include "malloc.h"
#include "mbuf.h"
#include "map.h"
#include "buf.h"
#include "vmmac.h"
#include "socket.h"
#include "syslog.h"
-#include "malloc.h"
#include "../net/if.h"
int i, nclbytes, off;
if (hlen)
- off = CLBYTES - hlen;
+ off = MCLBYTES - hlen;
else
off = 0;
- nclbytes = CLBYTES * (clrnd(nmr) / CLSIZE);
+ nclbytes = roundup(nmr * NBPG, MCLBYTES);
if (hlen)
- nclbytes += CLBYTES;
+ nclbytes += MCLBYTES;
if (ifr[0].ifrw_addr)
cp = ifr[0].ifrw_addr - off;
else {
/*
* Pull read data off a interface.
- * Len is length of data, with local net header stripped.
+ * Totlen 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
+ * We copy the header from the trailer 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.
- * Prepend a pointer to the interface structure,
+ * Save a pointer to the interface structure and the total length,
* so that protocols can determine where incoming packets arrived.
* Note: we may be called to receive from a transmit buffer by some
* devices. In that case, we must force normal mapping of the buffer,
* changed when remapping the transmit buffers).
*/
struct mbuf *
-if_ubaget(ifu, ifr, totlen, off0, ifp)
+if_ubaget(ifu, ifr, totlen, off, ifp)
struct ifubinfo *ifu;
register struct ifrw *ifr;
- int totlen, off0;
+ register int totlen;
+ int off;
struct ifnet *ifp;
{
struct mbuf *top, **mp;
register struct mbuf *m;
- int off = off0, len;
register caddr_t cp = ifr->ifrw_addr + ifu->iff_hlen, pp;
+ register int len;
+ caddr_t epkt = cp + totlen;
top = 0;
mp = ⊤
+ /*
+ * Skip the trailer header (type and trailer length).
+ */
+ if (off) {
+ off += 2 * sizeof(u_short);
+ totlen -= 2 * sizeof(u_short);
+ cp += off;
+ }
+ MGETHDR(m, M_DONTWAIT, MT_DATA);
+ if (m == 0)
+ return ((struct mbuf *)NULL);
+ m->m_pkthdr.rcvif = ifp;
+ m->m_pkthdr.len = totlen;
+ m->m_len = MHLEN;
+
if (ifr->ifrw_flags & IFRW_W)
rcv_xmtbuf((struct ifxmt *)ifr);
+
while (totlen > 0) {
- MGET(m, M_DONTWAIT, MT_DATA);
- if (m == 0) {
- m_freem(top);
- top = 0;
- goto out;
+ if (top) {
+ MGET(m, M_DONTWAIT, MT_DATA);
+ if (m == 0) {
+ m_freem(top);
+ top = 0;
+ goto out;
+ }
+ m->m_len = MLEN;
}
- if (off) {
- len = totlen - off;
- cp = ifr->ifrw_addr + ifu->iff_hlen + off;
- } else
- len = totlen;
- if (len >= CLBYTES/2) {
+ len = min(totlen, epkt - cp);
+ if (len >= MINCLSIZE) {
struct pte *cpte, *ppte;
int x, *ip, i;
- /*
- * If doing the first mbuf and
- * the interface pointer hasn't been put in,
- * put it in a separate mbuf to preserve alignment.
- */
- if (ifp) {
- len = 0;
+ MCLGET(m, M_DONTWAIT);
+ if ((m->m_flags & M_EXT) == 0)
goto nopage;
- }
- MCLGET(m);
- if (m->m_len != CLBYTES)
- goto nopage;
- m->m_len = MIN(len, CLBYTES);
+ len = min(len, MCLBYTES);
+ m->m_len = len;
if (!claligned(cp))
goto copy;
ppte = kvtopte(pp);
x = btop(cp - ifr->ifrw_addr);
ip = (int *)&ifr->ifrw_mr[x];
- for (i = 0; i < CLSIZE; i++) {
+ for (i = 0; i < MCLBYTES/NBPG; i++) {
struct pte t;
t = *ppte; *ppte++ = *cpte; *cpte = t;
*ip++ = cpte++->pg_pfnum|ifr->ifrw_proto;
goto nocopy;
}
nopage:
- m->m_off = MMINOFF;
- if (ifp) {
+ if (len < m->m_len) {
/*
- * Leave room for ifp.
+ * Place initial small packet/header at end of mbuf.
*/
- m->m_len = MIN(MLEN - sizeof(ifp), len);
- m->m_off += sizeof(ifp);
- } else
- m->m_len = MIN(MLEN, len);
+ if (top == 0 && len + max_linkhdr <= m->m_len)
+ m->m_data += max_linkhdr;
+ m->m_len = len;
+ } else
+ len = m->m_len;
copy:
- bcopy(cp, mtod(m, caddr_t), (unsigned)m->m_len);
- cp += m->m_len;
+ bcopy(cp, mtod(m, caddr_t), (unsigned)len);
+ cp += len;
nocopy:
*mp = m;
mp = &m->m_next;
- if (off) {
- /* sort of an ALGOL-W style for statement... */
- off += m->m_len;
- if (off == totlen) {
- cp = ifr->ifrw_addr + ifu->iff_hlen;
- off = 0;
- totlen = off0;
- }
- } else
- totlen -= m->m_len;
- if (ifp) {
- /*
- * Prepend interface pointer to first mbuf.
- */
- m->m_len += sizeof(ifp);
- m->m_off -= sizeof(ifp);
- *(mtod(m, struct ifnet **)) = ifp;
- ifp = (struct ifnet *)0;
- }
+ totlen -= len;
+ if (cp == epkt)
+ cp = ifr->ifrw_addr + ifu->iff_hlen;
}
out:
if (ifr->ifrw_flags & IFRW_W)
char *cp;
while (i = ffs((long)ifw->ifw_xswapd)) {
- cp = ifw->ifw_base + i * CLBYTES;
+ cp = ifw->ifw_base + i * MCLBYTES;
i--;
ifw->ifw_xswapd &= ~(1<<i);
mprev = &ifw->ifw_xtofree;
mprev = &m->m_next;
if (m == NULL)
break;
- bcopy(mtod(m, caddr_t), cp, CLBYTES);
+ bcopy(mtod(m, caddr_t), cp, MCLBYTES);
(void) m_free(m);
*mprev = NULL;
}
while (m) {
dp = mtod(m, char *);
if (claligned(cp) && claligned(dp) &&
- (m->m_len == CLBYTES || m->m_next == (struct mbuf *)0)) {
+ (m->m_len == MCLBYTES || m->m_next == (struct mbuf *)0)) {
struct pte *pte;
int *ip;
pte = kvtopte(dp);
x = btop(cp - ifw->ifw_addr);
ip = (int *)&ifw->ifw_mr[x];
- for (i = 0; i < CLSIZE; i++)
+ for (i = 0; i < MCLBYTES/NBPG; i++)
*ip++ = ifw->ifw_proto | pte++->pg_pfnum;
- xswapd |= 1 << (x>>(CLSHIFT-PGSHIFT));
+ xswapd |= 1 << (x>>(MCLSHIFT-PGSHIFT));
mp = m->m_next;
m->m_next = ifw->ifw_xtofree;
ifw->ifw_xtofree = m;
* should be unmapped so original pages will be accessed by the device.
*/
cc = cp - ifw->ifw_addr;
- x = ((cc - ifu->iff_hlen) + CLBYTES - 1) >> CLSHIFT;
+ x = ((cc - ifu->iff_hlen) + MCLBYTES - 1) >> MCLSHIFT;
ifw->ifw_xswapd &= ~xswapd;
while (i = ffs((long)ifw->ifw_xswapd)) {
i--;
if (i >= x)
break;
ifw->ifw_xswapd &= ~(1<<i);
- i *= CLSIZE;
- for (t = 0; t < CLSIZE; t++) {
+ i *= MCLBYTES/NBPG;
+ for (t = 0; t < MCLBYTES/NBPG; t++) {
ifw->ifw_mr[i] = ifw->ifw_wmap[i];
i++;
}