1 /* 2 * Copyright (c) 1989 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)if_vba.c 1.3 (Berkeley) 06/28/90 8 */ 9 10 #include "param.h" 11 #include "systm.h" 12 #include "mbuf.h" 13 #include "buf.h" 14 #include "cmap.h" 15 #include "vmmac.h" 16 #include "socket.h" 17 18 #include "../tahoe/mtpr.h" 19 #include "../tahoe/pte.h" 20 21 #include "../tahoevba/vbavar.h" 22 23 #include "../net/if.h" 24 #include "../netinet/in.h" 25 #include "../netinet/if_ether.h" 26 27 #include "if_vba.h" 28 29 if_vbareserve(ifvba0, n, bufsize, extra, extrasize) 30 struct ifvba *ifvba0; 31 register int n; 32 int bufsize; 33 caddr_t *extra; 34 int extrasize; 35 { 36 register caddr_t cp; 37 register struct pte *pte; 38 register struct ifvba *ifvba = ifvba0; 39 struct ifvba *vlim = ifvba + n; 40 41 n = roundup(extrasize + (n * bufsize), NBPG); 42 cp = (caddr_t)malloc((u_long)n, M_DEVBUF, M_NOWAIT); 43 if ((n + kvtophys(cp)) > VB_MAXADDR24) { 44 free(cp, M_DEVBUF); 45 cp = 0; 46 } 47 if (cp == 0) { 48 printf("No memory for device buffer(s)\n"); 49 return (0); 50 } 51 /* 52 * Make raw buffer pages uncacheable. 53 */ 54 pte = kvtopte(cp); 55 for (n = btoc(n); n--; pte++) 56 pte->pg_nc = 1; 57 mtpr(TBIA, 0); 58 if (extra) { 59 *extra = cp; 60 cp += extrasize; 61 } 62 for (; ifvba < vlim; ifvba++) { 63 ifvba->iff_buffer = cp; 64 ifvba->iff_physaddr = kvtophys(cp); 65 cp += bufsize; 66 } 67 return (1); 68 } 69 /* 70 * Routine to copy from VERSAbus memory into mbufs. 71 * 72 * Warning: This makes the fairly safe assumption that 73 * mbufs have even lengths. 74 */ 75 struct mbuf * 76 if_vbaget(rxbuf, totlen, off, ifp, flags) 77 caddr_t rxbuf; 78 int totlen, off, flags; 79 struct ifnet *ifp; 80 { 81 register caddr_t cp; 82 register struct mbuf *m; 83 struct mbuf *top = 0, **mp = ⊤ 84 int len; 85 caddr_t packet_end; 86 87 rxbuf += sizeof (struct ether_header); 88 cp = rxbuf; 89 packet_end = cp + totlen; 90 if (off) { 91 off += 2 * sizeof(u_short); 92 totlen -= 2 *sizeof(u_short); 93 cp = rxbuf + off; 94 } 95 96 MGETHDR(m, M_DONTWAIT, MT_DATA); 97 if (m == 0) 98 return (0); 99 m->m_pkthdr.rcvif = ifp; 100 m->m_pkthdr.len = totlen; 101 m->m_len = MHLEN; 102 103 while (totlen > 0) { 104 if (top) { 105 MGET(m, M_DONTWAIT, MT_DATA); 106 if (m == 0) { 107 m_freem(top); 108 return (0); 109 } 110 m->m_len = MLEN; 111 } 112 len = min(totlen, (packet_end - cp)); 113 if (len >= MINCLSIZE) { 114 MCLGET(m, M_DONTWAIT); 115 if (m->m_flags & M_EXT) 116 m->m_len = len = min(len, MCLBYTES); 117 else 118 len = m->m_len; 119 } else { 120 /* 121 * Place initial small packet/header at end of mbuf. 122 */ 123 if (len < m->m_len) { 124 if (top == 0 && len + max_linkhdr <= m->m_len) 125 m->m_data += max_linkhdr; 126 m->m_len = len; 127 } else 128 len = m->m_len; 129 } 130 if (flags) 131 if_vba16copy(cp, mtod(m, caddr_t), (u_int)len); 132 else 133 bcopy(cp, mtod(m, caddr_t), (u_int)len); 134 135 *mp = m; 136 mp = &m->m_next; 137 totlen -= len; 138 cp += len; 139 if (cp == packet_end) 140 cp = rxbuf; 141 } 142 return (top); 143 } 144 145 if_vbaput(ifu, m0, flags) 146 caddr_t ifu; 147 struct mbuf *m0; 148 { 149 register struct mbuf *m = m0; 150 register caddr_t cp = ifu; 151 152 while (m) { 153 if (flags) 154 if_vba16copy(mtod(m, caddr_t), cp, (u_int)m->m_len); 155 else 156 bcopy(mtod(m, caddr_t), cp, (u_int)m->m_len); 157 cp += m->m_len; 158 MFREE(m, m0); 159 m = m0; 160 } 161 if ((int)cp & 1) 162 *cp++ = 0; 163 return (cp - ifu); 164 } 165 166 if_vba16copy(from, to, cnt) 167 register caddr_t from, to; 168 register unsigned cnt; 169 { 170 register c; 171 register short *f, *t; 172 173 if (((int)from&01) && ((int)to&01)) { 174 /* source & dest at odd addresses */ 175 *to++ = *from++; 176 --cnt; 177 } 178 if (cnt > 1 && (((int)to&01) == 0) && (((int)from&01) == 0)) { 179 t = (short *)to; 180 f = (short *)from; 181 for (c = cnt>>1; c; --c) /* even address copy */ 182 *t++ = *f++; 183 cnt &= 1; 184 if (cnt) { /* odd len */ 185 from = (caddr_t)f; 186 to = (caddr_t)t; 187 *to = *from; 188 } 189 } 190 while ((int)cnt-- > 0) /* one of the address(es) must be odd */ 191 *to++ = *from++; 192 } 193