/* * Copyright (c) 1989 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. 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 BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)if_vba.c 1.4 (Berkeley) 12/16/90 */ #include "sys/param.h" #include "sys/systm.h" #include "sys/mbuf.h" #include "sys/buf.h" #include "sys/cmap.h" #include "sys/vmmac.h" #include "sys/socket.h" #include "../include/mtpr.h" #include "../include/pte.h" #include "../vba/vbavar.h" #include "net/if.h" #include "netinet/in.h" #include "netinet/if_ether.h" #include "if_vba.h" if_vbareserve(ifvba0, n, bufsize, extra, extrasize) struct ifvba *ifvba0; register int n; int bufsize; caddr_t *extra; int extrasize; { register caddr_t cp; register struct pte *pte; register struct ifvba *ifvba = ifvba0; struct ifvba *vlim = ifvba + n; n = roundup(extrasize + (n * bufsize), NBPG); cp = (caddr_t)malloc((u_long)n, M_DEVBUF, M_NOWAIT); if ((n + kvtophys(cp)) > VB_MAXADDR24) { free(cp, M_DEVBUF); cp = 0; } if (cp == 0) { printf("No memory for device buffer(s)\n"); return (0); } /* * Make raw buffer pages uncacheable. */ pte = kvtopte(cp); for (n = btoc(n); n--; pte++) pte->pg_nc = 1; mtpr(TBIA, 0); if (extra) { *extra = cp; cp += extrasize; } for (; ifvba < vlim; ifvba++) { ifvba->iff_buffer = cp; ifvba->iff_physaddr = kvtophys(cp); cp += bufsize; } return (1); } /* * Routine to copy from VERSAbus memory into mbufs. * * Warning: This makes the fairly safe assumption that * mbufs have even lengths. */ struct mbuf * if_vbaget(rxbuf, totlen, off, ifp, flags) caddr_t rxbuf; int totlen, off, flags; struct ifnet *ifp; { register caddr_t cp; register struct mbuf *m; struct mbuf *top = 0, **mp = ⊤ int len; caddr_t packet_end; rxbuf += sizeof (struct ether_header); cp = rxbuf; packet_end = cp + totlen; if (off) { off += 2 * sizeof(u_short); totlen -= 2 *sizeof(u_short); cp = rxbuf + off; } MGETHDR(m, M_DONTWAIT, MT_DATA); if (m == 0) return (0); m->m_pkthdr.rcvif = ifp; m->m_pkthdr.len = totlen; m->m_len = MHLEN; while (totlen > 0) { if (top) { MGET(m, M_DONTWAIT, MT_DATA); if (m == 0) { m_freem(top); return (0); } m->m_len = MLEN; } len = min(totlen, (packet_end - cp)); if (len >= MINCLSIZE) { MCLGET(m, M_DONTWAIT); if (m->m_flags & M_EXT) m->m_len = len = min(len, MCLBYTES); else len = m->m_len; } else { /* * Place initial small packet/header at end of mbuf. */ if (len < m->m_len) { if (top == 0 && len + max_linkhdr <= m->m_len) m->m_data += max_linkhdr; m->m_len = len; } else len = m->m_len; } if (flags) if_vba16copy(cp, mtod(m, caddr_t), (u_int)len); else bcopy(cp, mtod(m, caddr_t), (u_int)len); *mp = m; mp = &m->m_next; totlen -= len; cp += len; if (cp == packet_end) cp = rxbuf; } return (top); } if_vbaput(ifu, m0, flags) caddr_t ifu; struct mbuf *m0; { register struct mbuf *m = m0; register caddr_t cp = ifu; while (m) { if (flags) if_vba16copy(mtod(m, caddr_t), cp, (u_int)m->m_len); else bcopy(mtod(m, caddr_t), cp, (u_int)m->m_len); cp += m->m_len; MFREE(m, m0); m = m0; } if ((int)cp & 1) *cp++ = 0; return (cp - ifu); } if_vba16copy(from, to, cnt) register caddr_t from, to; register unsigned cnt; { register c; register short *f, *t; if (((int)from&01) && ((int)to&01)) { /* source & dest at odd addresses */ *to++ = *from++; --cnt; } if (cnt > 1 && (((int)to&01) == 0) && (((int)from&01) == 0)) { t = (short *)to; f = (short *)from; for (c = cnt>>1; c; --c) /* even address copy */ *t++ = *f++; cnt &= 1; if (cnt) { /* odd len */ from = (caddr_t)f; to = (caddr_t)t; *to = *from; } } while ((int)cnt-- > 0) /* one of the address(es) must be odd */ *to++ = *from++; }