137112Ssklower /*
237112Ssklower * Copyright (c) 1989 The Regents of the University of California.
337112Ssklower * All rights reserved.
437112Ssklower *
544532Sbostic * %sccs.include.redist.c%
637112Ssklower *
7*45795Sbostic * @(#)if_vba.c 1.4 (Berkeley) 12/16/90
837112Ssklower */
937112Ssklower
10*45795Sbostic #include "sys/param.h"
11*45795Sbostic #include "sys/systm.h"
12*45795Sbostic #include "sys/mbuf.h"
13*45795Sbostic #include "sys/buf.h"
14*45795Sbostic #include "sys/cmap.h"
15*45795Sbostic #include "sys/vmmac.h"
16*45795Sbostic #include "sys/socket.h"
1737112Ssklower
18*45795Sbostic #include "../include/mtpr.h"
19*45795Sbostic #include "../include/pte.h"
2037112Ssklower
21*45795Sbostic #include "../vba/vbavar.h"
2237112Ssklower
23*45795Sbostic #include "net/if.h"
24*45795Sbostic #include "netinet/in.h"
25*45795Sbostic #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 *
if_vbaget(rxbuf,totlen,off,ifp,flags)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 = ⊤
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
if_vbaput(ifu,m0,flags)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
if_vba16copy(from,to,cnt)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