xref: /csrg-svn/sys/news3400/if/if_news.c (revision 53897)
1*53897Smckusick /*
2*53897Smckusick  * Copyright (c) 1992 The Regents of the University of California.
3*53897Smckusick  * All rights reserved.
4*53897Smckusick  *
5*53897Smckusick  * This code is derived from software contributed to Berkeley by
6*53897Smckusick  * Sony Corp. and Kazumasa Utashiro of Software Research Associates, Inc.
7*53897Smckusick  *
8*53897Smckusick  * %sccs.include.redist.c%
9*53897Smckusick  *
10*53897Smckusick  * from: $Hdr: if_news.c,v 4.300 91/06/09 06:26:01 root Rel41 $ SONY
11*53897Smckusick  *
12*53897Smckusick  *	@(#)if_news.c	7.1 (Berkeley) 06/04/92
13*53897Smckusick  */
14*53897Smckusick 
15*53897Smckusick #include "types.h"
16*53897Smckusick #include "../include/fix_machine_type.h"
17*53897Smckusick #include "../include/pte.h"
18*53897Smckusick 
19*53897Smckusick #include "param.h"
20*53897Smckusick #include "systm.h"
21*53897Smckusick #include "mbuf.h"
22*53897Smckusick #include "map.h"
23*53897Smckusick #include "buf.h"
24*53897Smckusick #include "socket.h"
25*53897Smckusick #include "proc.h"
26*53897Smckusick #include "user.h"
27*53897Smckusick 
28*53897Smckusick #include "../net/if.h"
29*53897Smckusick #include "../if/if_news.h"
30*53897Smckusick #include "../include/cpu.h"
31*53897Smckusick 
32*53897Smckusick #if MCLBYTES == CLBYTES && defined(CPU_DOUBLE)
33*53897Smckusick #define	USE_CLUSTER
34*53897Smckusick #endif
35*53897Smckusick 
36*53897Smckusick /*
37*53897Smckusick  * Routines supporting NEWS network interfaces.
38*53897Smckusick  */
39*53897Smckusick #define btomcl(x)       (((x) + MCLBYTES - 1) >> MCLSHIFT)
40*53897Smckusick 
41*53897Smckusick /*
42*53897Smckusick  * Init NEWS for interface on uban whose headers of size hlen are to
43*53897Smckusick  * end on a page boundary.  We also allocate page frames in the mbuffer pool
44*53897Smckusick  * for these pages.
45*53897Smckusick  */
46*53897Smckusick if_newsinit(ifn, hlen, nmr)
47*53897Smckusick 	register struct ifnews *ifn;
48*53897Smckusick 	int hlen, nmr;
49*53897Smckusick {
50*53897Smckusick #ifdef USE_CLUSTER
51*53897Smckusick 	register caddr_t cp;
52*53897Smckusick 	int ncl;
53*53897Smckusick 
54*53897Smckusick 	if (ifn->ifn_raddr)
55*53897Smckusick 		return (1);
56*53897Smckusick 	ncl = nmr;
57*53897Smckusick 	cp = malloc(btomcl(ctob(2 * ncl)), M_DEVBUF, M_NOWAIT); /*XXX*/
58*53897Smckusick 	if (cp == 0)
59*53897Smckusick 		return (0);
60*53897Smckusick 	ifn->ifn_raddr = cp + 4 - (hlen & 03);
61*53897Smckusick 	ifn->ifn_waddr = cp + ncl * MCLBYTES;
62*53897Smckusick #endif /* USE_CLUSTER */
63*53897Smckusick 	ifn->ifn_hlen = hlen;
64*53897Smckusick 	return (1);
65*53897Smckusick }
66*53897Smckusick 
67*53897Smckusick /*
68*53897Smckusick  * Pull read data off a interface.
69*53897Smckusick  * Len is length of data, with local net header stripped.
70*53897Smckusick  * Off is non-zero if a trailer protocol was used, and
71*53897Smckusick  * gives the offset of the trailer information.
72*53897Smckusick  * We copy the trailer information and then all the normal
73*53897Smckusick  * data into mbufs.  When large sized units are present
74*53897Smckusick  * on the interface on cluster boundaries we can get them more
75*53897Smckusick  * easily by remapping, and take advantage of this here.
76*53897Smckusick  */
77*53897Smckusick #ifdef NOTDEF /* use m_devget */
78*53897Smckusick struct mbuf *
79*53897Smckusick if_rnewsget(ifn, totlen, off, ifp)
80*53897Smckusick 	register struct ifnews *ifn;
81*53897Smckusick 	register int totlen, off;
82*53897Smckusick 	struct ifnet *ifp;
83*53897Smckusick {
84*53897Smckusick 	register struct mbuf **mp, *m;
85*53897Smckusick 	struct mbuf *top;
86*53897Smckusick 	register int len;
87*53897Smckusick 	register caddr_t cp = ifn->ifn_raddr + ifn->ifn_hlen;
88*53897Smckusick 	caddr_t epkt = cp + totlen;
89*53897Smckusick 
90*53897Smckusick #ifdef USE_CLUSTER
91*53897Smckusick 	if (totlen >= MHLEN && off == 0) {
92*53897Smckusick 		MGETHDR(m, M_DONTWAIT, MT_DATA);
93*53897Smckusick 		if (m == 0)
94*53897Smckusick 			return (0);
95*53897Smckusick 		m->m_pkthdr.rcvif = ifp;
96*53897Smckusick 		m->m_pkthdr.len = totlen;
97*53897Smckusick 		MCLGET(m, M_DONTWAIT);
98*53897Smckusick 		if (m->m_len != MCLBYTES) {
99*53897Smckusick 			struct mbuf *n;
100*53897Smckusick 
101*53897Smckusick 			MFREE(m, n);
102*53897Smckusick 			goto noncluster;
103*53897Smckusick 		}
104*53897Smckusick 		pageswap(cp - ifn->ifn_hlen, mtod(m, caddr_t),
105*53897Smckusick 		    totlen + ifn->ifn_hlen);
106*53897Smckusick 		m->m_len = totlen;
107*53897Smckusick 		m->m_data += ifn->ifn_hlen + 4 - (ifn->ifn_hlen & 03);
108*53897Smckusick 		return (m);
109*53897Smckusick 	}
110*53897Smckusick noncluster:
111*53897Smckusick #endif /* USE_CLUSTER */
112*53897Smckusick 	top = 0;
113*53897Smckusick 	mp = ⊤
114*53897Smckusick 	/*
115*53897Smckusick 	 * Skip the trailer header (type and trailer length).
116*53897Smckusick 	 */
117*53897Smckusick 	if (off) {
118*53897Smckusick 		off += 2 * sizeof(u_short);
119*53897Smckusick 		totlen -= 2 * sizeof(u_short);
120*53897Smckusick 		cp += off;
121*53897Smckusick 	}
122*53897Smckusick 	MGETHDR(m, M_DONTWAIT, MT_DATA);
123*53897Smckusick 	if (m == 0)
124*53897Smckusick 		return ((struct mbuf *)NULL);
125*53897Smckusick 	m->m_pkthdr.rcvif = ifp;
126*53897Smckusick 	m->m_pkthdr.len = totlen;
127*53897Smckusick 	m->m_len = MHLEN;
128*53897Smckusick 
129*53897Smckusick 	while (totlen > 0) {
130*53897Smckusick 		if (top) {
131*53897Smckusick 			MGET(m, M_DONTWAIT, MT_DATA);
132*53897Smckusick 			if (m == 0) {
133*53897Smckusick 				m_freem(top);
134*53897Smckusick 				return(0);
135*53897Smckusick 			}
136*53897Smckusick 			m->m_len = MLEN;
137*53897Smckusick 		}
138*53897Smckusick 
139*53897Smckusick 		if (totlen >= MINCLSIZE)
140*53897Smckusick 			MCLGET(m, M_DONTWAIT);
141*53897Smckusick 		if (m->m_flags & M_EXT)
142*53897Smckusick 			m->m_len = MIN(totlen, MCLBYTES);
143*53897Smckusick 		else if (totlen < m->m_len) {
144*53897Smckusick 			/*
145*53897Smckusick 			 * Place initial small packet/header at end of mbuf.
146*53897Smckusick 			 */
147*53897Smckusick 			if (top == 0 && totlen + max_linkhdr <= m->m_len)
148*53897Smckusick 				m->m_data += max_linkhdr;
149*53897Smckusick 			m->m_len = totlen;
150*53897Smckusick 		}
151*53897Smckusick 		len = m->m_len;
152*53897Smckusick copy:
153*53897Smckusick 		bcopy(cp, mtod(m, caddr_t), (unsigned)len);
154*53897Smckusick 		cp += len;
155*53897Smckusick nocopy:
156*53897Smckusick 		*mp = m;
157*53897Smckusick 		mp = &m->m_next;
158*53897Smckusick 		totlen -= len;
159*53897Smckusick 		if (cp == epkt)
160*53897Smckusick 			cp = ifn->ifn_raddr + ifn->ifn_hlen;
161*53897Smckusick 	}
162*53897Smckusick 	return (top);
163*53897Smckusick }
164*53897Smckusick #endif /* NOTDEF */
165*53897Smckusick 
166*53897Smckusick /*
167*53897Smckusick  * Map a chain of mbufs onto a network interface
168*53897Smckusick  * in preparation for an i/o operation.
169*53897Smckusick  * The argument chain of mbufs includes the local network header.
170*53897Smckusick  */
171*53897Smckusick if_wnewsput(ifn, m)
172*53897Smckusick 	register struct ifnews *ifn;
173*53897Smckusick 	register struct mbuf *m;
174*53897Smckusick {
175*53897Smckusick #ifdef CPU_DOUBLE
176*53897Smckusick 	register struct mbuf_segment *ms;
177*53897Smckusick 	register int n, i;
178*53897Smckusick 
179*53897Smckusick 	ifn->ifn_mbuf = m;
180*53897Smckusick 	ms = (struct mbuf_segment *)ifn->ifn_waddr;
181*53897Smckusick 	n = 0;
182*53897Smckusick 	while (m) {
183*53897Smckusick 		ms->ms_physaddr = kvtophys(mtod(m, caddr_t));
184*53897Smckusick 		ms->ms_size = m->m_len;
185*53897Smckusick 		if ((i = (ms->ms_physaddr & PGOFSET) + ms->ms_size) > NBPG) {
186*53897Smckusick 			i -= NBPG;
187*53897Smckusick 			ms->ms_size -= i;
188*53897Smckusick 			ms++;
189*53897Smckusick 			ms->ms_physaddr =
190*53897Smckusick 			    kvtophys(mtod(m, caddr_t) + m->m_len - i);
191*53897Smckusick 			ms->ms_size = i;
192*53897Smckusick 		}
193*53897Smckusick 		ms++;
194*53897Smckusick 		n += m->m_len;
195*53897Smckusick 		m = m->m_next;
196*53897Smckusick 	}
197*53897Smckusick 	ms->ms_physaddr = 0;
198*53897Smckusick 	return (n);
199*53897Smckusick #else /* CPU_DOUBLE */
200*53897Smckusick 	register struct mbuf *mp;
201*53897Smckusick 	register caddr_t cp;
202*53897Smckusick 
203*53897Smckusick 	cp = ifn->ifn_waddr;
204*53897Smckusick 	while (m) {
205*53897Smckusick #ifdef mips
206*53897Smckusick 		bxcopy(mtod(m, caddr_t), cp, (unsigned)m->m_len);
207*53897Smckusick #else
208*53897Smckusick 		bcopy(mtod(m, caddr_t), cp, (unsigned)m->m_len);
209*53897Smckusick #endif
210*53897Smckusick 		cp += m->m_len;
211*53897Smckusick 		MFREE(m, mp);
212*53897Smckusick 		m = mp;
213*53897Smckusick 	}
214*53897Smckusick 	return (cp - ifn->ifn_waddr);
215*53897Smckusick #endif /* CPU_DOUBLE */
216*53897Smckusick }
217