# 2.11BSD#431 - /usr/src/sys/vaxif/if_uba.c

##### Functions

    if_ubaget         X
    if_ubaminit       X
    if_ubaput         X

       1: /*
       2:  * Copyright (c) 1982, 1986 Regents of the University of California.
       3:  * All rights reserved.  The Berkeley software License Agreement
       4:  * specifies the terms and conditions for redistribution.
       5:  *
       6:  *	@(#)if_uba.c	7.5.1.1 (Berkeley) 6/4/87
       7:  */
       8:
       9: #include "../machine/pte.h"
      10:
      11: #include "param.h"
      12: #include "systm.h"
      13: #include "mbuf.h"
      14: #include "map.h"
      15: #include "buf.h"
      16: #include "cmap.h"
      17: #include "vmmac.h"
      18: #include "socket.h"
      19: #include "syslog.h"
      20:
      21: #include "../net/if.h"
      22:
      23: #include "../vax/mtpr.h"
      24: #include "if_uba.h"
      25: #include "../vaxuba/ubareg.h"
      26: #include "../vaxuba/ubavar.h"
      27:
      28: /*
      29:  * Routines supporting UNIBUS network interfaces.
      30:  *
      31:  * TODO:
      32:  *	Support interfaces using only one BDP statically.
      33:  */
      34:
      35: /*
      36:  * Init UNIBUS for interface on uban whose headers of size hlen are to
      37:  * end on a page boundary.  We allocate a UNIBUS map register for the page
      38:  * with the header, and nmr more UNIBUS map registers for i/o on the adapter,
      39:  * doing this once for each read and once for each write buffer.  We also
      40:  * allocate page frames in the mbuffer pool for these pages.
      41:  */
      42: if_ubaminit(ifu, uban, hlen, nmr, ifr, nr, ifw, nw)
      43:     register struct ifubinfo *ifu;
      44:     int uban, hlen, nmr, nr, nw;
      45:     register struct ifrw *ifr;
      46:     register struct ifxmt *ifw;
      47: {
      48:     register caddr_t p;
      49:     caddr_t cp;
      50:     int i, ncl, off;
      51:
      52:     if (hlen)
      53:         off = CLBYTES - hlen;
      54:     else
      55:         off = 0;
      56:     ncl = clrnd(nmr) / CLSIZE;
      57:     if (hlen)
      58:         ncl++;
      59:     if (ifr[0].ifrw_addr)
      60:         cp = ifr[0].ifrw_addr - off;
      61:     else {
      62:         cp = m_clalloc((nr + nw) * ncl, MPG_SPACE, M_DONTWAIT);
      63:         if (cp == 0)
      64:             return (0);
      65:         p = cp;
      66:         for (i = 0; i < nr; i++) {
      67:             ifr[i].ifrw_addr = p + off;
      68:             p += ncl * CLBYTES;
      69:         }
      70:         for (i = 0; i < nw; i++) {
      71:             ifw[i].ifw_base = p;
      72:             ifw[i].ifw_addr = p + off;
      73:             p += ncl * CLBYTES;
      74:         }
      75:         ifu->iff_hlen = hlen;
      76:         ifu->iff_uban = uban;
      77:         ifu->iff_uba = uba_hd[uban].uh_uba;
      78:     }
      79:     for (i = 0; i < nr; i++)
      80:         if (if_ubaalloc(ifu, &ifr[i], nmr) == 0) {
      81:             nr = i;
      82:             nw = 0;
      83:             goto bad;
      84:         }
      85:     for (i = 0; i < nw; i++)
      86:         if (if_ubaalloc(ifu, &ifw[i].ifrw, nmr) == 0) {
      87:             nw = i;
      88:             goto bad;
      89:         }
      90:     while (--nw >= 0) {
      91:         for (i = 0; i < nmr; i++)
      92:             ifw[nw].ifw_wmap[i] = ifw[nw].ifw_mr[i];
      93:         ifw[nw].ifw_xswapd = 0;
      94:         ifw[nw].ifw_flags = IFRW_W;
      95:         ifw[nw].ifw_nmr = nmr;
      96:     }
      97:     return (1);
      98: bad:
      99:     while (--nw >= 0)
     100:         ubarelse(ifu->iff_uban, &ifw[nw].ifw_info);
     101:     while (--nr >= 0)
     102:         ubarelse(ifu->iff_uban, &ifr[nr].ifrw_info);
     103:     m_pgfree(cp, (nr + nw) * ncl);
     104:     ifr[0].ifrw_addr = 0;
     105:     return (0);
     106: }
     107:
     108: /*
     109:  * Setup an ifrw structure by allocating UNIBUS map registers,
     110:  * possibly a buffered data path, and initializing the fields of
     111:  * the ifrw structure to minimize run-time overhead.
     112:  */
     113: static
     114: if_ubaalloc(ifu, ifrw, nmr)
     115:     struct ifubinfo *ifu;
     116:     register struct ifrw *ifrw;
     117:     int nmr;
     118: {
     119:     register int info;
     120:
     121:     info =
     122:         uballoc(ifu->iff_uban, ifrw->ifrw_addr, nmr*NBPG + ifu->iff_hlen,
     123:             ifu->iff_flags);
     124:     if (info == 0)
     125:         return (0);
     126:     ifrw->ifrw_info = info;
     127:     ifrw->ifrw_bdp = UBAI_BDP(info);
     128:     ifrw->ifrw_proto = UBAMR_MRV | (UBAI_BDP(info) << UBAMR_DPSHIFT);
     129:     ifrw->ifrw_mr = &ifu->iff_uba->uba_map[UBAI_MR(info) + (ifu->iff_hlen?
     130:         1 : 0)];
     131:     return (1);
     132: }
     133:
     134: /*
     135:  * Pull read data off a interface.
     136:  * Len is length of data, with local net header stripped.
     137:  * Off is non-zero if a trailer protocol was used, and
     138:  * gives the offset of the trailer information.
     139:  * We copy the trailer information and then all the normal
     140:  * data into mbufs.  When full cluster sized units are present
     141:  * on the interface on cluster boundaries we can get them more
     142:  * easily by remapping, and take advantage of this here.
     143:  * Prepend a pointer to the interface structure,
     144:  * so that protocols can determine where incoming packets arrived.
     145:  * Note: we may be called to receive from a transmit buffer by some
     146:  * devices.  In that case, we must force normal mapping of the buffer,
     147:  * so that the correct data will appear (only unibus maps are
     148:  * changed when remapping the transmit buffers).
     149:  */
     150: struct mbuf *
     151: if_ubaget(ifu, ifr, totlen, off0, ifp)
     152:     struct ifubinfo *ifu;
     153:     register struct ifrw *ifr;
     154:     int totlen, off0;
     155:     struct ifnet *ifp;
     156: {
     157:     struct mbuf *top, **mp;
     158:     register struct mbuf *m;
     159:     int off = off0, len;
     160:     register caddr_t cp = ifr->ifrw_addr + ifu->iff_hlen, pp;
     161:
     162:     top = 0;
     163:     mp = &top;
     164:     if (ifr->ifrw_flags & IFRW_W)
     165:         rcv_xmtbuf((struct ifxmt *)ifr);
     166:     while (totlen > 0) {
     167:         MGET(m, M_DONTWAIT, MT_DATA);
     168:         if (m == 0) {
     169:             m_freem(top);
     170:             top = 0;
     171:             goto out;
     172:         }
     173:         if (off) {
     174:             len = totlen - off;
     175:             cp = ifr->ifrw_addr + ifu->iff_hlen + off;
     176:         } else
     177:             len = totlen;
     178:         if (len >= CLBYTES/2) {
     179:             struct pte *cpte, *ppte;
     180:             int x, *ip, i;
     181:
     182:             /*
     183: 			 * If doing the first mbuf and
     184: 			 * the interface pointer hasn't been put in,
     185: 			 * put it in a separate mbuf to preserve alignment.
     186: 			 */
     187:             if (ifp) {
     188:                 len = 0;
     189:                 goto nopage;
     190:             }
     191:             MCLGET(m);
     192:             if (m->m_len != CLBYTES)
     193:                 goto nopage;
     194:             m->m_len = MIN(len, CLBYTES);
     195:             if (!claligned(cp))
     196:                 goto copy;
     197:
     198:             /*
     199: 			 * Switch pages mapped to UNIBUS with new page pp,
     200: 			 * as quick form of copy.  Remap UNIBUS and invalidate.
     201: 			 */
     202:             pp = mtod(m, char *);
     203:             cpte = &Mbmap[mtocl(cp)*CLSIZE];
     204:             ppte = &Mbmap[mtocl(pp)*CLSIZE];
     205:             x = btop(cp - ifr->ifrw_addr);
     206:             ip = (int *)&ifr->ifrw_mr[x];
     207:             for (i = 0; i < CLSIZE; i++) {
     208:                 struct pte t;
     209:                 t = *ppte; *ppte++ = *cpte; *cpte = t;
     210:                 *ip++ =
     211:                     cpte++->pg_pfnum|ifr->ifrw_proto;
     212:                 mtpr(TBIS, cp);
     213:                 cp += NBPG;
     214:                 mtpr(TBIS, (caddr_t)pp);
     215:                 pp += NBPG;
     216:             }
     217:             goto nocopy;
     218:         }
     219: nopage:
     220:         m->m_off = MMINOFF;
     221:         if (ifp) {
     222:             /*
     223: 			 * Leave room for ifp.
     224: 			 */
     225:             m->m_len = MIN(MLEN - sizeof(ifp), len);
     226:             m->m_off += sizeof(ifp);
     227:         } else
     228:             m->m_len = MIN(MLEN, len);
     229: copy:
     230:         bcopy(cp, mtod(m, caddr_t), (unsigned)m->m_len);
     231:         cp += m->m_len;
     232: nocopy:
     233:         *mp = m;
     234:         mp = &m->m_next;
     235:         if (off) {
     236:             /* sort of an ALGOL-W style for statement... */
     237:             off += m->m_len;
     238:             if (off == totlen) {
     239:                 cp = ifr->ifrw_addr + ifu->iff_hlen;
     240:                 off = 0;
     241:                 totlen = off0;
     242:             }
     243:         } else
     244:             totlen -= m->m_len;
     245:         if (ifp) {
     246:             /*
     247: 			 * Prepend interface pointer to first mbuf.
     248: 			 */
     249:             m->m_len += sizeof(ifp);
     250:             m->m_off -= sizeof(ifp);
     251:             *(mtod(m, struct ifnet **)) = ifp;
     252:             ifp = (struct ifnet *)0;
     253:         }
     254:     }
     255: out:
     256:     if (ifr->ifrw_flags & IFRW_W)
     257:         restor_xmtbuf((struct ifxmt *)ifr);
     258:     return (top);
     259: }
     260:
     261: /*
     262:  * Change the mapping on a transmit buffer so that if_ubaget may
     263:  * receive from that buffer.  Copy data from any pages mapped to Unibus
     264:  * into the pages mapped to normal kernel virtual memory, so that
     265:  * they can be accessed and swapped as usual.  We take advantage
     266:  * of the fact that clusters are placed on the xtofree list
     267:  * in inverse order, finding the last one.
     268:  */
     269: static
     270: rcv_xmtbuf(ifw)
     271:     register struct ifxmt *ifw;
     272: {
     273:     register struct mbuf *m;
     274:     struct mbuf **mprev;
     275:     register i;
     276:     char *cp;
     277:
     278:     while (i = ffs((long)ifw->ifw_xswapd)) {
     279:         cp = ifw->ifw_base + i * CLBYTES;
     280:         i--;
     281:         ifw->ifw_xswapd &= ~(1<<i);
     282:         mprev = &ifw->ifw_xtofree;
     283:         for (m = ifw->ifw_xtofree; m && m->m_next; m = m->m_next)
     284:             mprev = &m->m_next;
     285:         if (m == NULL)
     286:             break;
     287:         bcopy(mtod(m, caddr_t), cp, CLBYTES);
     288:         (void) m_free(m);
     289:         *mprev = NULL;
     290:     }
     291:     ifw->ifw_xswapd = 0;
     292:     for (i = 0; i < ifw->ifw_nmr; i++)
     293:         ifw->ifw_mr[i] = ifw->ifw_wmap[i];
     294: }
     295:
     296: /*
     297:  * Put a transmit buffer back together after doing an if_ubaget on it,
     298:  * which may have swapped pages.
     299:  */
     300: static
     301: restor_xmtbuf(ifw)
     302:     register struct ifxmt *ifw;
     303: {
     304:     register i;
     305:
     306:     for (i = 0; i < ifw->ifw_nmr; i++)
     307:         ifw->ifw_wmap[i] = ifw->ifw_mr[i];
     308: }
     309:
     310: /*
     311:  * Map a chain of mbufs onto a network interface
     312:  * in preparation for an i/o operation.
     313:  * The argument chain of mbufs includes the local network
     314:  * header which is copied to be in the mapped, aligned
     315:  * i/o space.
     316:  */
     317: if_ubaput(ifu, ifw, m)
     318:     struct ifubinfo *ifu;
     319:     register struct ifxmt *ifw;
     320:     register struct mbuf *m;
     321: {
     322:     register struct mbuf *mp;
     323:     register caddr_t cp, dp;
     324:     register int i;
     325:     int xswapd = 0;
     326:     int x, cc, t;
     327:
     328:     cp = ifw->ifw_addr;
     329:     while (m) {
     330:         dp = mtod(m, char *);
     331:         if (claligned(cp) && claligned(dp) &&
     332:             (m->m_len == CLBYTES || m->m_next == (struct mbuf *)0)) {
     333:             struct pte *pte; int *ip;
     334:             pte = &Mbmap[mtocl(dp)*CLSIZE];
     335:             x = btop(cp - ifw->ifw_addr);
     336:             ip = (int *)&ifw->ifw_mr[x];
     337:             for (i = 0; i < CLSIZE; i++)
     338:                 *ip++ =
     339:                     ifw->ifw_proto | pte++->pg_pfnum;
     340:             xswapd |= 1 << (x>>(CLSHIFT-PGSHIFT));
     341:             mp = m->m_next;
     342:             m->m_next = ifw->ifw_xtofree;
     343:             ifw->ifw_xtofree = m;
     344:             cp += m->m_len;
     345:         } else {
     346:             bcopy(mtod(m, caddr_t), cp, (unsigned)m->m_len);
     347:             cp += m->m_len;
     348:             MFREE(m, mp);
     349:         }
     350:         m = mp;
     351:     }
     352:
     353:     /*
     354: 	 * Xswapd is the set of clusters we just mapped out.  Ifu->iff_xswapd
     355: 	 * is the set of clusters mapped out from before.  We compute
     356: 	 * the number of clusters involved in this operation in x.
     357: 	 * Clusters mapped out before and involved in this operation
     358: 	 * should be unmapped so original pages will be accessed by the device.
     359: 	 */
     360:     cc = cp - ifw->ifw_addr;
     361:     x = ((cc - ifu->iff_hlen) + CLBYTES - 1) >> CLSHIFT;
     362:     ifw->ifw_xswapd &= ~xswapd;
     363:     while (i = ffs((long)ifw->ifw_xswapd)) {
     364:         i--;
     365:         if (i >= x)
     366:             break;
     367:         ifw->ifw_xswapd &= ~(1<<i);
     368:         i *= CLSIZE;
     369:         for (t = 0; t < CLSIZE; t++) {
     370:             ifw->ifw_mr[i] = ifw->ifw_wmap[i];
     371:             i++;
     372:         }
     373:     }
     374:     ifw->ifw_xswapd |= xswapd;
     375:     return (cc);
     376: }

#### Defined functions

if_ubaalloc defined in line 113; used 2 times

- in line 80, 86

if_ubaget defined in line 150; never used
if_ubaminit defined in line 42; never used
if_ubaput defined in line 317; never used
rcv_xmtbuf defined in line 269; used 1 times

- in line 165

restor_xmtbuf defined in line 300; used 1 times

- in line 257

Last modified: 1987-06-06 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 360 |