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