137112Ssklower /* 237112Ssklower * Copyright (c) 1989 The Regents of the University of California. 337112Ssklower * All rights reserved. 437112Ssklower * 537112Ssklower * Redistribution and use in source and binary forms are permitted 637112Ssklower * provided that the above copyright notice and this paragraph are 737112Ssklower * duplicated in all such forms and that any documentation, 837112Ssklower * advertising materials, and other materials related to such 937112Ssklower * distribution and use acknowledge that the software was developed 1037112Ssklower * by the University of California, Berkeley. The name of the 1137112Ssklower * University may not be used to endorse or promote products derived 1237112Ssklower * from this software without specific prior written permission. 1337112Ssklower * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1437112Ssklower * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1537112Ssklower * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1637112Ssklower * 17*37474Ssklower * @(#)if_vba.c 1.2 (Berkeley) 04/22/89 1837112Ssklower */ 1937112Ssklower 2037112Ssklower #include "param.h" 2137112Ssklower #include "systm.h" 2237112Ssklower #include "mbuf.h" 2337112Ssklower #include "buf.h" 2437112Ssklower #include "cmap.h" 2537112Ssklower #include "vmmac.h" 2637112Ssklower #include "socket.h" 2737112Ssklower 2837112Ssklower #include "../tahoe/mtpr.h" 2937112Ssklower #include "../tahoe/pte.h" 3037112Ssklower 3137112Ssklower #include "../tahoevba/vbavar.h" 3237112Ssklower 3337112Ssklower #include "../net/if.h" 3437112Ssklower #include "../netinet/in.h" 3537112Ssklower #include "../netinet/if_ether.h" 3637112Ssklower 3737112Ssklower #include "if_vba.h" 3837112Ssklower 39*37474Ssklower if_vbareserve(ifvba0, n, bufsize, extra, extrasize) 4037112Ssklower struct ifvba *ifvba0; 4137112Ssklower register int n; 42*37474Ssklower int bufsize; 43*37474Ssklower caddr_t *extra; 44*37474Ssklower int extrasize; 4537112Ssklower { 4637112Ssklower register caddr_t cp; 4737112Ssklower register struct pte *pte; 4837112Ssklower register struct ifvba *ifvba = ifvba0; 4937112Ssklower struct ifvba *vlim = ifvba + n; 5037112Ssklower 51*37474Ssklower n = roundup(extrasize + (n * bufsize), NBPG); 5237112Ssklower cp = (caddr_t)malloc((u_long)n, M_DEVBUF, M_NOWAIT); 53*37474Ssklower if ((n + kvtophys(cp)) > VB_MAXADDR24) { 54*37474Ssklower free(cp, M_DEVBUF); 55*37474Ssklower cp = 0; 56*37474Ssklower } 5737112Ssklower if (cp == 0) { 58*37474Ssklower printf("No memory for device buffer(s)\n"); 5937112Ssklower return (0); 6037112Ssklower } 6137112Ssklower /* 6237112Ssklower * Make raw buffer pages uncacheable. 6337112Ssklower */ 6437112Ssklower pte = kvtopte(cp); 6537112Ssklower for (n = btoc(n); n--; pte++) 6637112Ssklower pte->pg_nc = 1; 6737112Ssklower mtpr(TBIA, 0); 68*37474Ssklower if (extra) { 69*37474Ssklower *extra = cp; 70*37474Ssklower cp += extrasize; 71*37474Ssklower } 7237112Ssklower for (; ifvba < vlim; ifvba++) { 7337112Ssklower ifvba->iff_buffer = cp; 7437112Ssklower ifvba->iff_physaddr = kvtophys(cp); 75*37474Ssklower cp += bufsize; 7637112Ssklower } 7737112Ssklower return (1); 7837112Ssklower } 7937112Ssklower /* 8037112Ssklower * Routine to copy from VERSAbus memory into mbufs. 8137112Ssklower * 8237112Ssklower * Warning: This makes the fairly safe assumption that 8337112Ssklower * mbufs have even lengths. 8437112Ssklower */ 8537112Ssklower struct mbuf * 8637112Ssklower if_vbaget(rxbuf, totlen, off, ifp, flags) 87*37474Ssklower caddr_t rxbuf; 8837112Ssklower int totlen, off, flags; 8937112Ssklower struct ifnet *ifp; 9037112Ssklower { 91*37474Ssklower register caddr_t cp; 9237112Ssklower register struct mbuf *m; 9337112Ssklower struct mbuf *top = 0, **mp = ⊤ 9437112Ssklower int len; 95*37474Ssklower caddr_t packet_end; 9637112Ssklower 9737112Ssklower rxbuf += sizeof (struct ether_header); 9837112Ssklower cp = rxbuf; 9937112Ssklower packet_end = cp + totlen; 10037112Ssklower if (off) { 10137112Ssklower off += 2 * sizeof(u_short); 10237112Ssklower totlen -= 2 *sizeof(u_short); 10337112Ssklower cp = rxbuf + off; 10437112Ssklower } 10537112Ssklower 10637112Ssklower MGETHDR(m, M_DONTWAIT, MT_DATA); 10737112Ssklower if (m == 0) 10837112Ssklower return (0); 10937112Ssklower m->m_pkthdr.rcvif = ifp; 11037112Ssklower m->m_pkthdr.len = totlen; 11137112Ssklower m->m_len = MHLEN; 11237112Ssklower 11337112Ssklower while (totlen > 0) { 11437112Ssklower if (top) { 11537112Ssklower MGET(m, M_DONTWAIT, MT_DATA); 11637112Ssklower if (m == 0) { 11737112Ssklower m_freem(top); 11837112Ssklower return (0); 11937112Ssklower } 12037112Ssklower m->m_len = MLEN; 12137112Ssklower } 12237112Ssklower len = min(totlen, (packet_end - cp)); 12337112Ssklower if (len >= MINCLSIZE) { 12437112Ssklower MCLGET(m, M_DONTWAIT); 12537112Ssklower if (m->m_flags & M_EXT) 12637112Ssklower m->m_len = len = min(len, MCLBYTES); 12737112Ssklower else 12837112Ssklower len = m->m_len; 12937112Ssklower } else { 13037112Ssklower /* 13137112Ssklower * Place initial small packet/header at end of mbuf. 13237112Ssklower */ 13337112Ssklower if (len < m->m_len) { 13437112Ssklower if (top == 0 && len + max_linkhdr <= m->m_len) 13537112Ssklower m->m_data += max_linkhdr; 13637112Ssklower m->m_len = len; 13737112Ssklower } else 13837112Ssklower len = m->m_len; 13937112Ssklower } 14037112Ssklower if (flags) 141*37474Ssklower if_vba16copy(cp, mtod(m, caddr_t), (u_int)len); 14237112Ssklower else 143*37474Ssklower bcopy(cp, mtod(m, caddr_t), (u_int)len); 14437112Ssklower 14537112Ssklower *mp = m; 14637112Ssklower mp = &m->m_next; 14737112Ssklower totlen -= len; 14837112Ssklower cp += len; 14937112Ssklower if (cp == packet_end) 15037112Ssklower cp = rxbuf; 15137112Ssklower } 15237112Ssklower return (top); 15337112Ssklower } 15437112Ssklower 15537112Ssklower if_vbaput(ifu, m0, flags) 156*37474Ssklower caddr_t ifu; 157*37474Ssklower struct mbuf *m0; 15837112Ssklower { 15937112Ssklower register struct mbuf *m = m0; 160*37474Ssklower register caddr_t cp = ifu; 16137112Ssklower 16237112Ssklower while (m) { 16337112Ssklower if (flags) 164*37474Ssklower if_vba16copy(mtod(m, caddr_t), cp, (u_int)m->m_len); 16537112Ssklower else 166*37474Ssklower bcopy(mtod(m, caddr_t), cp, (u_int)m->m_len); 16737112Ssklower cp += m->m_len; 16837112Ssklower MFREE(m, m0); 16937112Ssklower m = m0; 17037112Ssklower } 17137112Ssklower if ((int)cp & 1) 17237112Ssklower *cp++ = 0; 17337112Ssklower return (cp - ifu); 17437112Ssklower } 17537112Ssklower 17637112Ssklower if_vba16copy(from, to, cnt) 177*37474Ssklower register caddr_t from, to; 178*37474Ssklower register unsigned cnt; 17937112Ssklower { 18037112Ssklower register c; 18137112Ssklower register short *f, *t; 18237112Ssklower 18337112Ssklower if (((int)from&01) && ((int)to&01)) { 18437112Ssklower /* source & dest at odd addresses */ 18537112Ssklower *to++ = *from++; 18637112Ssklower --cnt; 18737112Ssklower } 18837112Ssklower if (cnt > 1 && (((int)to&01) == 0) && (((int)from&01) == 0)) { 18937112Ssklower t = (short *)to; 19037112Ssklower f = (short *)from; 19137112Ssklower for (c = cnt>>1; c; --c) /* even address copy */ 19237112Ssklower *t++ = *f++; 19337112Ssklower cnt &= 1; 19437112Ssklower if (cnt) { /* odd len */ 195*37474Ssklower from = (caddr_t)f; 196*37474Ssklower to = (caddr_t)t; 19737112Ssklower *to = *from; 19837112Ssklower } 19937112Ssklower } 20037112Ssklower while ((int)cnt-- > 0) /* one of the address(es) must be odd */ 20137112Ssklower *to++ = *from++; 20237112Ssklower } 203