Commit | Line | Data |
---|---|---|
0a0089df KS |
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 | * | |
385e8f24 | 17 | * @(#)if_vba.c 1.2 (Berkeley) %G% |
0a0089df KS |
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 | ||
385e8f24 | 39 | if_vbareserve(ifvba0, n, bufsize, extra, extrasize) |
0a0089df KS |
40 | struct ifvba *ifvba0; |
41 | register int n; | |
385e8f24 KS |
42 | int bufsize; |
43 | caddr_t *extra; | |
44 | int extrasize; | |
0a0089df KS |
45 | { |
46 | register caddr_t cp; | |
47 | register struct pte *pte; | |
48 | register struct ifvba *ifvba = ifvba0; | |
49 | struct ifvba *vlim = ifvba + n; | |
50 | ||
385e8f24 | 51 | n = roundup(extrasize + (n * bufsize), NBPG); |
0a0089df | 52 | cp = (caddr_t)malloc((u_long)n, M_DEVBUF, M_NOWAIT); |
385e8f24 KS |
53 | if ((n + kvtophys(cp)) > VB_MAXADDR24) { |
54 | free(cp, M_DEVBUF); | |
55 | cp = 0; | |
56 | } | |
0a0089df | 57 | if (cp == 0) { |
385e8f24 | 58 | printf("No memory for device buffer(s)\n"); |
0a0089df KS |
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); | |
385e8f24 KS |
68 | if (extra) { |
69 | *extra = cp; | |
70 | cp += extrasize; | |
71 | } | |
0a0089df KS |
72 | for (; ifvba < vlim; ifvba++) { |
73 | ifvba->iff_buffer = cp; | |
74 | ifvba->iff_physaddr = kvtophys(cp); | |
385e8f24 | 75 | cp += bufsize; |
0a0089df KS |
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) | |
385e8f24 | 87 | caddr_t rxbuf; |
0a0089df KS |
88 | int totlen, off, flags; |
89 | struct ifnet *ifp; | |
90 | { | |
385e8f24 | 91 | register caddr_t cp; |
0a0089df KS |
92 | register struct mbuf *m; |
93 | struct mbuf *top = 0, **mp = ⊤ | |
94 | int len; | |
385e8f24 | 95 | caddr_t packet_end; |
0a0089df KS |
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) | |
385e8f24 | 141 | if_vba16copy(cp, mtod(m, caddr_t), (u_int)len); |
0a0089df | 142 | else |
385e8f24 | 143 | bcopy(cp, mtod(m, caddr_t), (u_int)len); |
0a0089df KS |
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) | |
385e8f24 KS |
156 | caddr_t ifu; |
157 | struct mbuf *m0; | |
0a0089df KS |
158 | { |
159 | register struct mbuf *m = m0; | |
385e8f24 | 160 | register caddr_t cp = ifu; |
0a0089df KS |
161 | |
162 | while (m) { | |
163 | if (flags) | |
385e8f24 | 164 | if_vba16copy(mtod(m, caddr_t), cp, (u_int)m->m_len); |
0a0089df | 165 | else |
385e8f24 | 166 | bcopy(mtod(m, caddr_t), cp, (u_int)m->m_len); |
0a0089df KS |
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) | |
385e8f24 KS |
177 | register caddr_t from, to; |
178 | register unsigned cnt; | |
0a0089df KS |
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 */ | |
385e8f24 KS |
195 | from = (caddr_t)f; |
196 | to = (caddr_t)t; | |
0a0089df KS |
197 | *to = *from; |
198 | } | |
199 | } | |
200 | while ((int)cnt-- > 0) /* one of the address(es) must be odd */ | |
201 | *to++ = *from++; | |
202 | } |