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.1 (Berkeley) 03/09/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, size) 40 struct ifvba *ifvba0; 41 register int n; 42 int size; 43 { 44 register caddr_t cp; 45 register struct pte *pte; 46 register struct ifvba *ifvba = ifvba0; 47 struct ifvba *vlim = ifvba + n; 48 49 n = roundup(n * size, NBPG); 50 cp = (caddr_t)malloc((u_long)n, M_DEVBUF, M_NOWAIT); 51 if (cp == 0) { 52 printf("No memory for device buffer\n"); 53 return (0); 54 } 55 /* 56 * Make raw buffer pages uncacheable. 57 */ 58 pte = kvtopte(cp); 59 for (n = btoc(n); n--; pte++) 60 pte->pg_nc = 1; 61 mtpr(TBIA, 0); 62 for (; ifvba < vlim; ifvba++) { 63 ifvba->iff_buffer = cp; 64 ifvba->iff_physaddr = kvtophys(cp); 65 cp += size; 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 u_char *rxbuf; 78 int totlen, off, flags; 79 struct ifnet *ifp; 80 { 81 register u_char *cp; 82 register struct mbuf *m; 83 struct mbuf *top = 0, **mp = ⊤ 84 int len; 85 u_char *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, u_char *), (u_int)len); 132 else 133 bcopy(cp, mtod(m, u_char *), (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 register u_char *ifu; 147 register struct mbuf *m0; 148 { 149 register struct mbuf *m = m0; 150 register u_char *cp = ifu; 151 152 while (m) { 153 if (flags) 154 if_vba16copy(mtod(m, u_char *), cp, m->m_len); 155 else 156 bcopy(mtod(m, u_char *), cp, 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 u_char *from, *to; 168 register u_int 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 = (u_char *)f; 186 to = (u_char *)t; 187 *to = *from; 188 } 189 } 190 while ((int)cnt-- > 0) /* one of the address(es) must be odd */ 191 *to++ = *from++; 192 } 193