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