xref: /csrg-svn/sys/tahoe/if/if_vba.c (revision 37474)
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 = &top;
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