xref: /original-bsd/sys/tahoe/if/if_vba.c (revision fbcc2ded)
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.3 (Berkeley) 06/28/90
8  */
9 
10 #include "param.h"
11 #include "systm.h"
12 #include "mbuf.h"
13 #include "buf.h"
14 #include "cmap.h"
15 #include "vmmac.h"
16 #include "socket.h"
17 
18 #include "../tahoe/mtpr.h"
19 #include "../tahoe/pte.h"
20 
21 #include "../tahoevba/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 *
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 = &top;
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 
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 
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