137112Ssklower /* 237112Ssklower * Copyright (c) 1989 The Regents of the University of California. 337112Ssklower * All rights reserved. 437112Ssklower * 5*44532Sbostic * %sccs.include.redist.c% 637112Ssklower * 7*44532Sbostic * @(#)if_vba.c 1.3 (Berkeley) 06/28/90 837112Ssklower */ 937112Ssklower 1037112Ssklower #include "param.h" 1137112Ssklower #include "systm.h" 1237112Ssklower #include "mbuf.h" 1337112Ssklower #include "buf.h" 1437112Ssklower #include "cmap.h" 1537112Ssklower #include "vmmac.h" 1637112Ssklower #include "socket.h" 1737112Ssklower 1837112Ssklower #include "../tahoe/mtpr.h" 1937112Ssklower #include "../tahoe/pte.h" 2037112Ssklower 2137112Ssklower #include "../tahoevba/vbavar.h" 2237112Ssklower 2337112Ssklower #include "../net/if.h" 2437112Ssklower #include "../netinet/in.h" 2537112Ssklower #include "../netinet/if_ether.h" 2637112Ssklower 2737112Ssklower #include "if_vba.h" 2837112Ssklower 2937474Ssklower if_vbareserve(ifvba0, n, bufsize, extra, extrasize) 3037112Ssklower struct ifvba *ifvba0; 3137112Ssklower register int n; 3237474Ssklower int bufsize; 3337474Ssklower caddr_t *extra; 3437474Ssklower int extrasize; 3537112Ssklower { 3637112Ssklower register caddr_t cp; 3737112Ssklower register struct pte *pte; 3837112Ssklower register struct ifvba *ifvba = ifvba0; 3937112Ssklower struct ifvba *vlim = ifvba + n; 4037112Ssklower 4137474Ssklower n = roundup(extrasize + (n * bufsize), NBPG); 4237112Ssklower cp = (caddr_t)malloc((u_long)n, M_DEVBUF, M_NOWAIT); 4337474Ssklower if ((n + kvtophys(cp)) > VB_MAXADDR24) { 4437474Ssklower free(cp, M_DEVBUF); 4537474Ssklower cp = 0; 4637474Ssklower } 4737112Ssklower if (cp == 0) { 4837474Ssklower printf("No memory for device buffer(s)\n"); 4937112Ssklower return (0); 5037112Ssklower } 5137112Ssklower /* 5237112Ssklower * Make raw buffer pages uncacheable. 5337112Ssklower */ 5437112Ssklower pte = kvtopte(cp); 5537112Ssklower for (n = btoc(n); n--; pte++) 5637112Ssklower pte->pg_nc = 1; 5737112Ssklower mtpr(TBIA, 0); 5837474Ssklower if (extra) { 5937474Ssklower *extra = cp; 6037474Ssklower cp += extrasize; 6137474Ssklower } 6237112Ssklower for (; ifvba < vlim; ifvba++) { 6337112Ssklower ifvba->iff_buffer = cp; 6437112Ssklower ifvba->iff_physaddr = kvtophys(cp); 6537474Ssklower cp += bufsize; 6637112Ssklower } 6737112Ssklower return (1); 6837112Ssklower } 6937112Ssklower /* 7037112Ssklower * Routine to copy from VERSAbus memory into mbufs. 7137112Ssklower * 7237112Ssklower * Warning: This makes the fairly safe assumption that 7337112Ssklower * mbufs have even lengths. 7437112Ssklower */ 7537112Ssklower struct mbuf * 7637112Ssklower if_vbaget(rxbuf, totlen, off, ifp, flags) 7737474Ssklower caddr_t rxbuf; 7837112Ssklower int totlen, off, flags; 7937112Ssklower struct ifnet *ifp; 8037112Ssklower { 8137474Ssklower register caddr_t cp; 8237112Ssklower register struct mbuf *m; 8337112Ssklower struct mbuf *top = 0, **mp = ⊤ 8437112Ssklower int len; 8537474Ssklower caddr_t packet_end; 8637112Ssklower 8737112Ssklower rxbuf += sizeof (struct ether_header); 8837112Ssklower cp = rxbuf; 8937112Ssklower packet_end = cp + totlen; 9037112Ssklower if (off) { 9137112Ssklower off += 2 * sizeof(u_short); 9237112Ssklower totlen -= 2 *sizeof(u_short); 9337112Ssklower cp = rxbuf + off; 9437112Ssklower } 9537112Ssklower 9637112Ssklower MGETHDR(m, M_DONTWAIT, MT_DATA); 9737112Ssklower if (m == 0) 9837112Ssklower return (0); 9937112Ssklower m->m_pkthdr.rcvif = ifp; 10037112Ssklower m->m_pkthdr.len = totlen; 10137112Ssklower m->m_len = MHLEN; 10237112Ssklower 10337112Ssklower while (totlen > 0) { 10437112Ssklower if (top) { 10537112Ssklower MGET(m, M_DONTWAIT, MT_DATA); 10637112Ssklower if (m == 0) { 10737112Ssklower m_freem(top); 10837112Ssklower return (0); 10937112Ssklower } 11037112Ssklower m->m_len = MLEN; 11137112Ssklower } 11237112Ssklower len = min(totlen, (packet_end - cp)); 11337112Ssklower if (len >= MINCLSIZE) { 11437112Ssklower MCLGET(m, M_DONTWAIT); 11537112Ssklower if (m->m_flags & M_EXT) 11637112Ssklower m->m_len = len = min(len, MCLBYTES); 11737112Ssklower else 11837112Ssklower len = m->m_len; 11937112Ssklower } else { 12037112Ssklower /* 12137112Ssklower * Place initial small packet/header at end of mbuf. 12237112Ssklower */ 12337112Ssklower if (len < m->m_len) { 12437112Ssklower if (top == 0 && len + max_linkhdr <= m->m_len) 12537112Ssklower m->m_data += max_linkhdr; 12637112Ssklower m->m_len = len; 12737112Ssklower } else 12837112Ssklower len = m->m_len; 12937112Ssklower } 13037112Ssklower if (flags) 13137474Ssklower if_vba16copy(cp, mtod(m, caddr_t), (u_int)len); 13237112Ssklower else 13337474Ssklower bcopy(cp, mtod(m, caddr_t), (u_int)len); 13437112Ssklower 13537112Ssklower *mp = m; 13637112Ssklower mp = &m->m_next; 13737112Ssklower totlen -= len; 13837112Ssklower cp += len; 13937112Ssklower if (cp == packet_end) 14037112Ssklower cp = rxbuf; 14137112Ssklower } 14237112Ssklower return (top); 14337112Ssklower } 14437112Ssklower 14537112Ssklower if_vbaput(ifu, m0, flags) 14637474Ssklower caddr_t ifu; 14737474Ssklower struct mbuf *m0; 14837112Ssklower { 14937112Ssklower register struct mbuf *m = m0; 15037474Ssklower register caddr_t cp = ifu; 15137112Ssklower 15237112Ssklower while (m) { 15337112Ssklower if (flags) 15437474Ssklower if_vba16copy(mtod(m, caddr_t), cp, (u_int)m->m_len); 15537112Ssklower else 15637474Ssklower bcopy(mtod(m, caddr_t), cp, (u_int)m->m_len); 15737112Ssklower cp += m->m_len; 15837112Ssklower MFREE(m, m0); 15937112Ssklower m = m0; 16037112Ssklower } 16137112Ssklower if ((int)cp & 1) 16237112Ssklower *cp++ = 0; 16337112Ssklower return (cp - ifu); 16437112Ssklower } 16537112Ssklower 16637112Ssklower if_vba16copy(from, to, cnt) 16737474Ssklower register caddr_t from, to; 16837474Ssklower register unsigned cnt; 16937112Ssklower { 17037112Ssklower register c; 17137112Ssklower register short *f, *t; 17237112Ssklower 17337112Ssklower if (((int)from&01) && ((int)to&01)) { 17437112Ssklower /* source & dest at odd addresses */ 17537112Ssklower *to++ = *from++; 17637112Ssklower --cnt; 17737112Ssklower } 17837112Ssklower if (cnt > 1 && (((int)to&01) == 0) && (((int)from&01) == 0)) { 17937112Ssklower t = (short *)to; 18037112Ssklower f = (short *)from; 18137112Ssklower for (c = cnt>>1; c; --c) /* even address copy */ 18237112Ssklower *t++ = *f++; 18337112Ssklower cnt &= 1; 18437112Ssklower if (cnt) { /* odd len */ 18537474Ssklower from = (caddr_t)f; 18637474Ssklower to = (caddr_t)t; 18737112Ssklower *to = *from; 18837112Ssklower } 18937112Ssklower } 19037112Ssklower while ((int)cnt-- > 0) /* one of the address(es) must be odd */ 19137112Ssklower *to++ = *from++; 19237112Ssklower } 193