xref: /csrg-svn/sys/tahoe/if/if_vba.c (revision 37474)
137112Ssklower /*
237112Ssklower  * Copyright (c) 1989 The Regents of the University of California.
337112Ssklower  * All rights reserved.
437112Ssklower  *
537112Ssklower  * Redistribution and use in source and binary forms are permitted
637112Ssklower  * provided that the above copyright notice and this paragraph are
737112Ssklower  * duplicated in all such forms and that any documentation,
837112Ssklower  * advertising materials, and other materials related to such
937112Ssklower  * distribution and use acknowledge that the software was developed
1037112Ssklower  * by the University of California, Berkeley.  The name of the
1137112Ssklower  * University may not be used to endorse or promote products derived
1237112Ssklower  * from this software without specific prior written permission.
1337112Ssklower  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1437112Ssklower  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1537112Ssklower  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1637112Ssklower  *
17*37474Ssklower  *	@(#)if_vba.c	1.2 (Berkeley) 04/22/89
1837112Ssklower  */
1937112Ssklower 
2037112Ssklower #include "param.h"
2137112Ssklower #include "systm.h"
2237112Ssklower #include "mbuf.h"
2337112Ssklower #include "buf.h"
2437112Ssklower #include "cmap.h"
2537112Ssklower #include "vmmac.h"
2637112Ssklower #include "socket.h"
2737112Ssklower 
2837112Ssklower #include "../tahoe/mtpr.h"
2937112Ssklower #include "../tahoe/pte.h"
3037112Ssklower 
3137112Ssklower #include "../tahoevba/vbavar.h"
3237112Ssklower 
3337112Ssklower #include "../net/if.h"
3437112Ssklower #include "../netinet/in.h"
3537112Ssklower #include "../netinet/if_ether.h"
3637112Ssklower 
3737112Ssklower #include "if_vba.h"
3837112Ssklower 
39*37474Ssklower if_vbareserve(ifvba0, n, bufsize, extra, extrasize)
4037112Ssklower struct ifvba *ifvba0;
4137112Ssklower register int n;
42*37474Ssklower int bufsize;
43*37474Ssklower caddr_t *extra;
44*37474Ssklower int extrasize;
4537112Ssklower {
4637112Ssklower 	register caddr_t cp;
4737112Ssklower 	register struct pte *pte;
4837112Ssklower 	register struct ifvba *ifvba = ifvba0;
4937112Ssklower 	struct ifvba *vlim  = ifvba + n;
5037112Ssklower 
51*37474Ssklower 	n = roundup(extrasize + (n * bufsize), NBPG);
5237112Ssklower 	cp = (caddr_t)malloc((u_long)n, M_DEVBUF, M_NOWAIT);
53*37474Ssklower 	if ((n + kvtophys(cp)) > VB_MAXADDR24) {
54*37474Ssklower 		free(cp, M_DEVBUF);
55*37474Ssklower 		cp = 0;
56*37474Ssklower 	}
5737112Ssklower 	if (cp == 0) {
58*37474Ssklower 		printf("No memory for device buffer(s)\n");
5937112Ssklower 		return (0);
6037112Ssklower 	}
6137112Ssklower 	/*
6237112Ssklower 	 * Make raw buffer pages uncacheable.
6337112Ssklower 	 */
6437112Ssklower 	pte = kvtopte(cp);
6537112Ssklower 	for (n = btoc(n); n--; pte++)
6637112Ssklower 		pte->pg_nc = 1;
6737112Ssklower 	mtpr(TBIA, 0);
68*37474Ssklower 	if (extra) {
69*37474Ssklower 		*extra = cp;
70*37474Ssklower 		cp += extrasize;
71*37474Ssklower 	}
7237112Ssklower 	for (; ifvba < vlim; ifvba++) {
7337112Ssklower 		ifvba->iff_buffer = cp;
7437112Ssklower 		ifvba->iff_physaddr = kvtophys(cp);
75*37474Ssklower 		cp += bufsize;
7637112Ssklower 	}
7737112Ssklower 	return (1);
7837112Ssklower }
7937112Ssklower /*
8037112Ssklower  * Routine to copy from VERSAbus memory into mbufs.
8137112Ssklower  *
8237112Ssklower  * Warning: This makes the fairly safe assumption that
8337112Ssklower  * mbufs have even lengths.
8437112Ssklower  */
8537112Ssklower struct mbuf *
8637112Ssklower if_vbaget(rxbuf, totlen, off, ifp, flags)
87*37474Ssklower 	caddr_t rxbuf;
8837112Ssklower 	int totlen, off, flags;
8937112Ssklower 	struct ifnet *ifp;
9037112Ssklower {
91*37474Ssklower 	register caddr_t cp;
9237112Ssklower 	register struct mbuf *m;
9337112Ssklower 	struct mbuf *top = 0, **mp = &top;
9437112Ssklower 	int len;
95*37474Ssklower 	caddr_t packet_end;
9637112Ssklower 
9737112Ssklower 	rxbuf += sizeof (struct ether_header);
9837112Ssklower 	cp = rxbuf;
9937112Ssklower 	packet_end = cp + totlen;
10037112Ssklower 	if (off) {
10137112Ssklower 		off += 2 * sizeof(u_short);
10237112Ssklower 		totlen -= 2 *sizeof(u_short);
10337112Ssklower 		cp = rxbuf + off;
10437112Ssklower 	}
10537112Ssklower 
10637112Ssklower 	MGETHDR(m, M_DONTWAIT, MT_DATA);
10737112Ssklower 	if (m == 0)
10837112Ssklower 		return (0);
10937112Ssklower 	m->m_pkthdr.rcvif = ifp;
11037112Ssklower 	m->m_pkthdr.len = totlen;
11137112Ssklower 	m->m_len = MHLEN;
11237112Ssklower 
11337112Ssklower 	while (totlen > 0) {
11437112Ssklower 		if (top) {
11537112Ssklower 			MGET(m, M_DONTWAIT, MT_DATA);
11637112Ssklower 			if (m == 0) {
11737112Ssklower 				m_freem(top);
11837112Ssklower 				return (0);
11937112Ssklower 			}
12037112Ssklower 			m->m_len = MLEN;
12137112Ssklower 		}
12237112Ssklower 		len = min(totlen, (packet_end - cp));
12337112Ssklower 		if (len >= MINCLSIZE) {
12437112Ssklower 			MCLGET(m, M_DONTWAIT);
12537112Ssklower 			if (m->m_flags & M_EXT)
12637112Ssklower 				m->m_len = len = min(len, MCLBYTES);
12737112Ssklower 			else
12837112Ssklower 				len = m->m_len;
12937112Ssklower 		} else {
13037112Ssklower 			/*
13137112Ssklower 			 * Place initial small packet/header at end of mbuf.
13237112Ssklower 			 */
13337112Ssklower 			if (len < m->m_len) {
13437112Ssklower 				if (top == 0 && len + max_linkhdr <= m->m_len)
13537112Ssklower 					m->m_data += max_linkhdr;
13637112Ssklower 				m->m_len = len;
13737112Ssklower 			} else
13837112Ssklower 				len = m->m_len;
13937112Ssklower 		}
14037112Ssklower 		if (flags)
141*37474Ssklower 			if_vba16copy(cp, mtod(m, caddr_t), (u_int)len);
14237112Ssklower 		else
143*37474Ssklower 			bcopy(cp, mtod(m, caddr_t), (u_int)len);
14437112Ssklower 
14537112Ssklower 		*mp = m;
14637112Ssklower 		mp = &m->m_next;
14737112Ssklower 		totlen -= len;
14837112Ssklower 		cp += len;
14937112Ssklower 		if (cp == packet_end)
15037112Ssklower 			cp = rxbuf;
15137112Ssklower 	}
15237112Ssklower 	return (top);
15337112Ssklower }
15437112Ssklower 
15537112Ssklower if_vbaput(ifu, m0, flags)
156*37474Ssklower caddr_t ifu;
157*37474Ssklower struct mbuf *m0;
15837112Ssklower {
15937112Ssklower 	register struct mbuf *m = m0;
160*37474Ssklower 	register caddr_t cp = ifu;
16137112Ssklower 
16237112Ssklower 	while (m) {
16337112Ssklower 		if (flags)
164*37474Ssklower 			if_vba16copy(mtod(m, caddr_t), cp, (u_int)m->m_len);
16537112Ssklower 		else
166*37474Ssklower 			bcopy(mtod(m, caddr_t), cp, (u_int)m->m_len);
16737112Ssklower 		cp += m->m_len;
16837112Ssklower 		MFREE(m, m0);
16937112Ssklower 		m = m0;
17037112Ssklower 	}
17137112Ssklower 	if ((int)cp & 1)
17237112Ssklower 		*cp++ = 0;
17337112Ssklower 	return (cp - ifu);
17437112Ssklower }
17537112Ssklower 
17637112Ssklower if_vba16copy(from, to, cnt)
177*37474Ssklower 	register caddr_t from, to;
178*37474Ssklower 	register unsigned cnt;
17937112Ssklower {
18037112Ssklower 	register c;
18137112Ssklower 	register short *f, *t;
18237112Ssklower 
18337112Ssklower 	if (((int)from&01) && ((int)to&01)) {
18437112Ssklower 		/* source & dest at odd addresses */
18537112Ssklower 		*to++ = *from++;
18637112Ssklower 		--cnt;
18737112Ssklower 	}
18837112Ssklower 	if (cnt > 1 && (((int)to&01) == 0) && (((int)from&01) == 0)) {
18937112Ssklower 		t = (short *)to;
19037112Ssklower 		f = (short *)from;
19137112Ssklower 		for (c = cnt>>1; c; --c)	/* even address copy */
19237112Ssklower 			*t++ = *f++;
19337112Ssklower 		cnt &= 1;
19437112Ssklower 		if (cnt) {			/* odd len */
195*37474Ssklower 			from = (caddr_t)f;
196*37474Ssklower 			to = (caddr_t)t;
19737112Ssklower 			*to = *from;
19837112Ssklower 		}
19937112Ssklower 	}
20037112Ssklower 	while ((int)cnt-- > 0)	/* one of the address(es) must be odd */
20137112Ssklower 		*to++ = *from++;
20237112Ssklower }
203