xref: /csrg-svn/sys/tahoe/if/if_vba.c (revision 44532)
137112Ssklower /*
237112Ssklower  * Copyright (c) 1989 The Regents of the University of California.
337112Ssklower  * All rights reserved.
437112Ssklower  *
5*44532Sbostic  * %sccs.include.redist.c%
637112Ssklower  *
7*44532Sbostic  *	@(#)if_vba.c	1.3 (Berkeley) 06/28/90
837112Ssklower  */
937112Ssklower 
1037112Ssklower #include "param.h"
1137112Ssklower #include "systm.h"
1237112Ssklower #include "mbuf.h"
1337112Ssklower #include "buf.h"
1437112Ssklower #include "cmap.h"
1537112Ssklower #include "vmmac.h"
1637112Ssklower #include "socket.h"
1737112Ssklower 
1837112Ssklower #include "../tahoe/mtpr.h"
1937112Ssklower #include "../tahoe/pte.h"
2037112Ssklower 
2137112Ssklower #include "../tahoevba/vbavar.h"
2237112Ssklower 
2337112Ssklower #include "../net/if.h"
2437112Ssklower #include "../netinet/in.h"
2537112Ssklower #include "../netinet/if_ether.h"
2637112Ssklower 
2737112Ssklower #include "if_vba.h"
2837112Ssklower 
2937474Ssklower if_vbareserve(ifvba0, n, bufsize, extra, extrasize)
3037112Ssklower struct ifvba *ifvba0;
3137112Ssklower register int n;
3237474Ssklower int bufsize;
3337474Ssklower caddr_t *extra;
3437474Ssklower int extrasize;
3537112Ssklower {
3637112Ssklower 	register caddr_t cp;
3737112Ssklower 	register struct pte *pte;
3837112Ssklower 	register struct ifvba *ifvba = ifvba0;
3937112Ssklower 	struct ifvba *vlim  = ifvba + n;
4037112Ssklower 
4137474Ssklower 	n = roundup(extrasize + (n * bufsize), NBPG);
4237112Ssklower 	cp = (caddr_t)malloc((u_long)n, M_DEVBUF, M_NOWAIT);
4337474Ssklower 	if ((n + kvtophys(cp)) > VB_MAXADDR24) {
4437474Ssklower 		free(cp, M_DEVBUF);
4537474Ssklower 		cp = 0;
4637474Ssklower 	}
4737112Ssklower 	if (cp == 0) {
4837474Ssklower 		printf("No memory for device buffer(s)\n");
4937112Ssklower 		return (0);
5037112Ssklower 	}
5137112Ssklower 	/*
5237112Ssklower 	 * Make raw buffer pages uncacheable.
5337112Ssklower 	 */
5437112Ssklower 	pte = kvtopte(cp);
5537112Ssklower 	for (n = btoc(n); n--; pte++)
5637112Ssklower 		pte->pg_nc = 1;
5737112Ssklower 	mtpr(TBIA, 0);
5837474Ssklower 	if (extra) {
5937474Ssklower 		*extra = cp;
6037474Ssklower 		cp += extrasize;
6137474Ssklower 	}
6237112Ssklower 	for (; ifvba < vlim; ifvba++) {
6337112Ssklower 		ifvba->iff_buffer = cp;
6437112Ssklower 		ifvba->iff_physaddr = kvtophys(cp);
6537474Ssklower 		cp += bufsize;
6637112Ssklower 	}
6737112Ssklower 	return (1);
6837112Ssklower }
6937112Ssklower /*
7037112Ssklower  * Routine to copy from VERSAbus memory into mbufs.
7137112Ssklower  *
7237112Ssklower  * Warning: This makes the fairly safe assumption that
7337112Ssklower  * mbufs have even lengths.
7437112Ssklower  */
7537112Ssklower struct mbuf *
7637112Ssklower if_vbaget(rxbuf, totlen, off, ifp, flags)
7737474Ssklower 	caddr_t rxbuf;
7837112Ssklower 	int totlen, off, flags;
7937112Ssklower 	struct ifnet *ifp;
8037112Ssklower {
8137474Ssklower 	register caddr_t cp;
8237112Ssklower 	register struct mbuf *m;
8337112Ssklower 	struct mbuf *top = 0, **mp = &top;
8437112Ssklower 	int len;
8537474Ssklower 	caddr_t packet_end;
8637112Ssklower 
8737112Ssklower 	rxbuf += sizeof (struct ether_header);
8837112Ssklower 	cp = rxbuf;
8937112Ssklower 	packet_end = cp + totlen;
9037112Ssklower 	if (off) {
9137112Ssklower 		off += 2 * sizeof(u_short);
9237112Ssklower 		totlen -= 2 *sizeof(u_short);
9337112Ssklower 		cp = rxbuf + off;
9437112Ssklower 	}
9537112Ssklower 
9637112Ssklower 	MGETHDR(m, M_DONTWAIT, MT_DATA);
9737112Ssklower 	if (m == 0)
9837112Ssklower 		return (0);
9937112Ssklower 	m->m_pkthdr.rcvif = ifp;
10037112Ssklower 	m->m_pkthdr.len = totlen;
10137112Ssklower 	m->m_len = MHLEN;
10237112Ssklower 
10337112Ssklower 	while (totlen > 0) {
10437112Ssklower 		if (top) {
10537112Ssklower 			MGET(m, M_DONTWAIT, MT_DATA);
10637112Ssklower 			if (m == 0) {
10737112Ssklower 				m_freem(top);
10837112Ssklower 				return (0);
10937112Ssklower 			}
11037112Ssklower 			m->m_len = MLEN;
11137112Ssklower 		}
11237112Ssklower 		len = min(totlen, (packet_end - cp));
11337112Ssklower 		if (len >= MINCLSIZE) {
11437112Ssklower 			MCLGET(m, M_DONTWAIT);
11537112Ssklower 			if (m->m_flags & M_EXT)
11637112Ssklower 				m->m_len = len = min(len, MCLBYTES);
11737112Ssklower 			else
11837112Ssklower 				len = m->m_len;
11937112Ssklower 		} else {
12037112Ssklower 			/*
12137112Ssklower 			 * Place initial small packet/header at end of mbuf.
12237112Ssklower 			 */
12337112Ssklower 			if (len < m->m_len) {
12437112Ssklower 				if (top == 0 && len + max_linkhdr <= m->m_len)
12537112Ssklower 					m->m_data += max_linkhdr;
12637112Ssklower 				m->m_len = len;
12737112Ssklower 			} else
12837112Ssklower 				len = m->m_len;
12937112Ssklower 		}
13037112Ssklower 		if (flags)
13137474Ssklower 			if_vba16copy(cp, mtod(m, caddr_t), (u_int)len);
13237112Ssklower 		else
13337474Ssklower 			bcopy(cp, mtod(m, caddr_t), (u_int)len);
13437112Ssklower 
13537112Ssklower 		*mp = m;
13637112Ssklower 		mp = &m->m_next;
13737112Ssklower 		totlen -= len;
13837112Ssklower 		cp += len;
13937112Ssklower 		if (cp == packet_end)
14037112Ssklower 			cp = rxbuf;
14137112Ssklower 	}
14237112Ssklower 	return (top);
14337112Ssklower }
14437112Ssklower 
14537112Ssklower if_vbaput(ifu, m0, flags)
14637474Ssklower caddr_t ifu;
14737474Ssklower struct mbuf *m0;
14837112Ssklower {
14937112Ssklower 	register struct mbuf *m = m0;
15037474Ssklower 	register caddr_t cp = ifu;
15137112Ssklower 
15237112Ssklower 	while (m) {
15337112Ssklower 		if (flags)
15437474Ssklower 			if_vba16copy(mtod(m, caddr_t), cp, (u_int)m->m_len);
15537112Ssklower 		else
15637474Ssklower 			bcopy(mtod(m, caddr_t), cp, (u_int)m->m_len);
15737112Ssklower 		cp += m->m_len;
15837112Ssklower 		MFREE(m, m0);
15937112Ssklower 		m = m0;
16037112Ssklower 	}
16137112Ssklower 	if ((int)cp & 1)
16237112Ssklower 		*cp++ = 0;
16337112Ssklower 	return (cp - ifu);
16437112Ssklower }
16537112Ssklower 
16637112Ssklower if_vba16copy(from, to, cnt)
16737474Ssklower 	register caddr_t from, to;
16837474Ssklower 	register unsigned cnt;
16937112Ssklower {
17037112Ssklower 	register c;
17137112Ssklower 	register short *f, *t;
17237112Ssklower 
17337112Ssklower 	if (((int)from&01) && ((int)to&01)) {
17437112Ssklower 		/* source & dest at odd addresses */
17537112Ssklower 		*to++ = *from++;
17637112Ssklower 		--cnt;
17737112Ssklower 	}
17837112Ssklower 	if (cnt > 1 && (((int)to&01) == 0) && (((int)from&01) == 0)) {
17937112Ssklower 		t = (short *)to;
18037112Ssklower 		f = (short *)from;
18137112Ssklower 		for (c = cnt>>1; c; --c)	/* even address copy */
18237112Ssklower 			*t++ = *f++;
18337112Ssklower 		cnt &= 1;
18437112Ssklower 		if (cnt) {			/* odd len */
18537474Ssklower 			from = (caddr_t)f;
18637474Ssklower 			to = (caddr_t)t;
18737112Ssklower 			*to = *from;
18837112Ssklower 		}
18937112Ssklower 	}
19037112Ssklower 	while ((int)cnt-- > 0)	/* one of the address(es) must be odd */
19137112Ssklower 		*to++ = *from++;
19237112Ssklower }
193