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.4 (Berkeley) 12/16/90
8 */
9
10 #include "sys/param.h"
11 #include "sys/systm.h"
12 #include "sys/mbuf.h"
13 #include "sys/buf.h"
14 #include "sys/cmap.h"
15 #include "sys/vmmac.h"
16 #include "sys/socket.h"
17
18 #include "../include/mtpr.h"
19 #include "../include/pte.h"
20
21 #include "../vba/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 *
if_vbaget(rxbuf,totlen,off,ifp,flags)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
if_vbaput(ifu,m0,flags)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
if_vba16copy(from,to,cnt)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