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