# 2.11BSD#431 - /usr/src/sys/pdpif/if_en.c

##### Functions

    enattach          X
    encollide         X
    endocoll          X
    eninit            X
    enoutput          X
    enprobe           X
    enrint            X
    enstart           X
    enxint            X

##### Variables

    en_softc          X
    enalldelay        X
    endriver          X
    eninfo            X
    enlastdel         X
    enlastmask        X
    enstd             X
    pupdst            X
    pupproto          X
    pupsrc            X

##### Macros

    ENMRU             X
    ENMTU             X
    ENUNIT            X
    endataaddr        X

##### struct's

    en_softc          X

       1: /*
       2:  * Copyright (c) 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_en.c	1.3 (2.11BSD GTE) 1997/1/19
       7:  */
       8:
       9: #include "en.h"
      10: #if NEN > 0
      11:
      12: /*
      13:  * Xerox prototype (3 Mb) Ethernet interface driver.
      14:  */
      15:
      16: #include "param.h"
      17: #include "systm.h"
      18: #include "mbuf.h"
      19: #include "buf.h"
      20: #include "domain.h"
      21: #include "protosw.h"
      22: #include "socket.h"
      23: #include "pdpuba/ubavar.h"
      24: #include "if_enreg.h"
      25: #include "netinet/in.h"
      26: #include "netinet/in_systm.h"
      27: #include "net/netisr.h"
      28: #include "net/if.h"
      29: #include "pdpif/if_en.h"
      30: #include "pdpif/if_uba.h"
      31: #include "netinet/ip.h"
      32: #include "netinet/ip_var.h"
      33: #include "netinet/in_var.h"
      34: #include "net/route.h"
      35: #include "errno.h"
      36:
      37: #define ENMTU   (1024+512)
      38: #define ENMRU   (1024+512+16)       /* 16 is enough to receive trailer */
      39:
      40: int enprobe(), enattach(), enrint(), enxint(), encollide();
      41: struct  uba_device *eninfo[NEN];
      42: u_short enstd[] = { 0 };
      43: struct  uba_driver endriver =
      44:     { enprobe, 0, enattach, 0, enstd, "en", eninfo };
      45: #define ENUNIT(x)   minor(x)
      46:
      47: int eninit(),enoutput();
      48:
      49: /*
      50:  * Ethernet software status per interface.
      51:  *
      52:  * Each interface is referenced by a network interface structure,
      53:  * es_if, which the routing code uses to locate the interface.
      54:  * This structure contains the output queue for the interface, its address, ...
      55:  * We also have, for each interface, a UBA interface structure, which
      56:  * contains information about the UNIBUS resources held by the interface:
      57:  * map registers, buffered data paths, etc.  Information is cached in this
      58:  * structure for use by the if_uba.c routines in running the interface
      59:  * efficiently.
      60:  */
      61: struct  en_softc {
      62:     struct  ifnet es_if;        /* network-visible interface */
      63:     struct  ifuba es_ifuba;     /* UNIBUS resources */
      64:     short   es_delay;       /* current output delay */
      65:     short   es_mask;        /* mask for current output delay */
      66:     short   es_lastx;       /* host last transmitted to */
      67:     short   es_oactive;     /* is output active? */
      68:     short   es_olen;        /* length of last output */
      69: } en_softc[NEN];
      70:
      71: /*
      72:  * Do output DMA to determine interface presence and
      73:  * interrupt vector.  DMA is too short to disturb other hosts.
      74:  */
      75: enprobe(reg)
      76:     caddr_t reg;
      77: {
      78:     register int br, cvec;      /* r11, r10 value-result */
      79:     register struct endevice *addr = (struct endevice *)reg;
      80:
      81: #ifndef pdp11
      82: #ifdef lint
      83:     br = 0; cvec = br; br = cvec;
      84:     enrint(0); enxint(0); encollide(0);
      85: #endif
      86:     addr->en_istat = 0;
      87:     addr->en_owc = -1;
      88:     addr->en_oba = 0;
      89:     addr->en_ostat = EN_IEN|EN_GO;
      90:     DELAY(100000L);
      91:     addr->en_ostat = 0;
      92: #ifdef ECHACK
      93:     br = 0x16;
      94: #endif
      95: #endif
      96:     return (1);
      97: }
      98:
      99: /*
     100:  * Interface exists: make available by filling in network interface
     101:  * record.  System will initialize the interface when it is ready
     102:  * to accept packets.
     103:  */
     104: enattach(ui)
     105:     struct uba_device *ui;
     106: {
     107:     register struct en_softc *es = &en_softc[ui->ui_unit];
     108:     register struct sockaddr_in *sin;
     109:
     110:     es->es_if.if_unit = ui->ui_unit;
     111:     es->es_if.if_name = "en";
     112:     es->es_if.if_mtu = ENMTU;
     113:     es->es_if.if_flags = IFF_BROADCAST;
     114:     es->es_if.if_init = eninit;
     115:     es->es_if.if_output = enoutput;
     116:     es->es_ifuba.ifu_flags = UBA_NEEDBDP | UBA_NEED16 | UBA_CANTWAIT;
     117:     if_attach(&es->es_if);
     118: }
     119:
     120: /*
     121:  * Initialization of interface; clear recorded pending
     122:  * operations, and reinitialize UNIBUS usage.
     123:  */
     124: eninit(unit)
     125:     int unit;
     126: {
     127:     register struct en_softc *es = &en_softc[unit];
     128:     register struct uba_device *ui = eninfo[unit];
     129:     register struct endevice *addr;
     130:     int s;
     131:
     132:     if (if_ubainit(&es->es_ifuba, ui->ui_ubanum,
     133:         sizeof (struct en_header), (int)btoc(ENMRU)) == 0) {
     134:         printf("en%d: can't initialize\n", unit);
     135:         es->es_if.if_flags &= ~IFF_UP;
     136:         return;
     137:     }
     138:     addr = (struct endevice *)ui->ui_addr;
     139:     addr->en_istat = addr->en_ostat = 0;
     140:
     141:     /*
     142: 	 * Hang a receive and start any
     143: 	 * pending writes by faking a transmit complete.
     144: 	 */
     145:     s = splimp();
     146:     addr->en_iba = es->es_ifuba.ifu_r.ifrw_info;
     147:     addr->en_iwc = -(sizeof (struct en_header) + ENMRU) >> 1;
     148:     addr->en_istat = EN_IEN|EN_GO;
     149:     es->es_oactive = 1;
     150:     es->es_if.if_flags |= IFF_UP;
     151:     enxint(unit);
     152:     splx(s);
     153:     if_rtinit(&es->es_if, RTF_UP);
     154: }
     155:
     156: int enalldelay = 0;
     157: int enlastdel = 50;
     158: int enlastmask = (~0) << 5;
     159:
     160: /*
     161:  * Start or restart output on interface.
     162:  * If interface is already active, then this is a retransmit
     163:  * after a collision, and just restuff registers and delay.
     164:  * If interface is not already active, get another datagram
     165:  * to send off of the interface queue, and map it to the interface
     166:  * before starting the output.
     167:  */
     168: enstart(dev)
     169:     dev_t dev;
     170: {
     171:         int unit = ENUNIT(dev);
     172:     struct uba_device *ui = eninfo[unit];
     173:     register struct en_softc *es = &en_softc[unit];
     174:     register struct endevice *addr;
     175:     struct mbuf *m;
     176:     int dest;
     177:
     178:     if (es->es_oactive)
     179:         goto restart;
     180:
     181:     /*
     182: 	 * Not already active: dequeue another request
     183: 	 * and map it to the UNIBUS.  If no more requests,
     184: 	 * just return.
     185: 	 */
     186:     IF_DEQUEUE(&es->es_if.if_snd, m);
     187:     if (m == 0) {
     188:         es->es_oactive = 0;
     189:         return;
     190:     }
     191:     dest = mtod(m, struct en_header *)->en_dhost;
     192:     es->es_olen = if_wubaput(&es->es_ifuba, m);
     193:
     194:     /*
     195: 	 * Ethernet cannot take back-to-back packets (no
     196: 	 * buffering in interface.  To help avoid overrunning
     197: 	 * receivers, enforce a small delay (about 1ms) in interface:
     198: 	 *	* between all packets when enalldelay
     199: 	 *	* whenever last packet was broadcast
     200: 	 *	* whenever this packet is to same host as last packet
     201: 	 */
     202:     if (enalldelay || es->es_lastx == 0 || es->es_lastx == dest) {
     203:         es->es_delay = enlastdel;
     204:         es->es_mask = enlastmask;
     205:     }
     206:     es->es_lastx = dest;
     207:
     208: restart:
     209:     addr = (struct endevice *)ui->ui_addr;
     210:     addr->en_oba = (int)es->es_ifuba.ifu_w.ifrw_info;
     211:     addr->en_odelay = es->es_delay;
     212:     addr->en_owc = -((es->es_olen + 1) >> 1);
     213:     addr->en_ostat = EN_IEN|EN_GO;
     214:     es->es_oactive = 1;
     215: }
     216:
     217: /*
     218:  * Ethernet interface transmitter interrupt.
     219:  * Start another output if more data to send.
     220:  */
     221: enxint(unit)
     222:     int unit;
     223: {
     224:     register struct uba_device *ui = eninfo[unit];
     225:     register struct en_softc *es = &en_softc[unit];
     226:     register struct endevice *addr = (struct endevice *)ui->ui_addr;
     227:
     228:     if (es->es_oactive == 0)
     229:         return;
     230:     if (es->es_mask && (addr->en_ostat&EN_OERROR)) {
     231:         es->es_if.if_oerrors++;
     232:         endocoll(unit);
     233:         return;
     234:     }
     235:     es->es_if.if_opackets++;
     236:     es->es_oactive = 0;
     237:     es->es_delay = 0;
     238:     es->es_mask = ~0;
     239:     if (es->es_ifuba.ifu_xtofree) {
     240:         m_freem(es->es_ifuba.ifu_xtofree);
     241:         es->es_ifuba.ifu_xtofree = 0;
     242:     }
     243:     if (es->es_if.if_snd.ifq_head == 0) {
     244:         es->es_lastx = 256;     /* putatively illegal */
     245:         return;
     246:     }
     247:     enstart(unit);
     248: }
     249:
     250: /*
     251:  * Collision on ethernet interface.  Do exponential
     252:  * backoff, and retransmit.  If have backed off all
     253:  * the way print warning diagnostic, and drop packet.
     254:  */
     255: encollide(unit)
     256:     int unit;
     257: {
     258:     struct en_softc *es = &en_softc[unit];
     259:
     260:     es->es_if.if_collisions++;
     261:     if (es->es_oactive == 0)
     262:         return;
     263:     endocoll(unit);
     264: }
     265:
     266: endocoll(unit)
     267:     int unit;
     268: {
     269:     register struct en_softc *es = &en_softc[unit];
     270:
     271:     /*
     272: 	 * Es_mask is a 16 bit number with n low zero bits, with
     273: 	 * n the number of backoffs.  When es_mask is 0 we have
     274: 	 * backed off 16 times, and give up.
     275: 	 */
     276:     if (es->es_mask == 0) {
     277:         printf("en%d: send error\n", unit);
     278:         enxint(unit);
     279:         return;
     280:     }
     281:     /*
     282: 	 * Another backoff.
     283: 	 */
     284:     es->es_mask <<= 1;
     285:     es->es_delay = ffs(es->es_mask);
     286:     enstart(unit);
     287: }
     288:
     289: #ifdef  notdef
     290: struct  sockaddr_pup pupsrc = { AF_PUP };
     291: struct  sockaddr_pup pupdst = { AF_PUP };
     292: struct  sockproto pupproto = { PF_PUP };
     293: #endif
     294: /*
     295:  * Ethernet interface receiver interrupt.
     296:  * If input error just drop packet.
     297:  * Otherwise purge input buffered data path and examine
     298:  * packet to determine type.  If can't determine length
     299:  * from type, then have to drop packet.  Othewise decapsulate
     300:  * packet based on type and pass to type specific higher-level
     301:  * input routine.
     302:  */
     303: enrint(unit)
     304:     int unit;
     305: {
     306:     register struct en_softc *es = &en_softc[unit];
     307:     struct endevice *addr = (struct endevice *)eninfo[unit]->ui_addr;
     308:     register struct en_header *en;
     309:         struct mbuf *m;
     310:     int len, plen; short resid;
     311:     register struct ifqueue *inq;
     312:     int off;
     313:
     314:     es->es_if.if_ipackets++;
     315:
     316:     if (addr->en_istat&EN_IERROR) {
     317:         es->es_if.if_ierrors++;
     318:         goto setup;
     319:     }
     320:
     321:     /*
     322: 	 * Calculate input data length.
     323: 	 * Get pointer to ethernet header (in input buffer).
     324: 	 * Deal with trailer protocol: if type is PUP trailer
     325: 	 * get true type from first 16-bit word past data.
     326: 	 * Remember that type was trailer by setting off.
     327: 	 */
     328:     resid = addr->en_iwc;
     329:     if (resid)
     330:         resid |= 0176000;
     331:     len = (((sizeof (struct en_header) + ENMRU) >> 1) + resid) << 1;
     332:     len -= sizeof (struct en_header);
     333:     if (len > ENMRU)
     334:         goto setup;         /* sanity */
     335:     en = (struct en_header *)(es->es_ifuba.ifu_r.ifrw_info);
     336: #define endataaddr(en, off, type)   ((type)(((caddr_t)((en)+1)+(off))))
     337:     if (en->en_type >= ENPUP_TRAIL &&
     338:         en->en_type < ENPUP_TRAIL+ENPUP_NTRAILER) {
     339:         off = (en->en_type - ENPUP_TRAIL) * 512;
     340:         if (off > ENMTU)
     341:             goto setup;     /* sanity */
     342:         en->en_type = *endataaddr(en, off, u_short *);
     343:         resid = *(endataaddr(en, off+2, u_short *));
     344:         if (off + resid > len)
     345:             goto setup;     /* sanity */
     346:         len = off + resid;
     347:     } else
     348:         off = 0;
     349:     if (len == 0)
     350:         goto setup;
     351:     /*
     352: 	 * Pull packet off interface.  Off is nonzero if packet
     353: 	 * has trailing header; if_rubaget will then force this header
     354: 	 * information to be at the front, but we still have to drop
     355: 	 * the type and length which are at the front of any trailer data.
     356: 	 */
     357:     m = if_rubaget(&es->es_ifuba, len, off, &es->es_if);
     358:     if (m == 0)
     359:         goto setup;
     360:     if (off) {
     361:         m->m_off += 2 * sizeof (u_short);
     362:         m->m_len -= 2 * sizeof (u_short);
     363:     }
     364:     switch (en->en_type) {
     365:
     366: #ifdef INET
     367:     case ENPUP_IPTYPE:
     368:         schednetisr(NETISR_IP);
     369:         inq = &ipintrq;
     370:         break;
     371: #endif
     372: #ifdef PUP
     373:     case ENPUP_PUPTYPE: {
     374:         struct pup_header *pup = mtod(m, struct pup_header *);
     375:
     376:         pupproto.sp_protocol = pup->pup_type;
     377:         pupdst.spup_addr = pup->pup_dport;
     378:         pupsrc.spup_addr = pup->pup_sport;
     379:         raw_input(m, &pupproto, (struct sockaddr *)&pupsrc,
     380:           (struct sockaddr *)&pupdst);
     381:         goto setup;
     382:     }
     383: #endif
     384:     default:
     385:         m_freem(m);
     386:         goto setup;
     387:     }
     388:
     389:     if (IF_QFULL(inq)) {
     390:         IF_DROP(inq);
     391:         m_freem(m);
     392:     } else
     393:         IF_ENQUEUE(inq, m);
     394:
     395: setup:
     396:     /*
     397: 	 * Reset for next packet.
     398: 	 */
     399:     addr->en_iba = es->es_ifuba.ifu_r.ifrw_info;
     400:     addr->en_iwc = -(sizeof (struct en_header) + ENMRU) >> 1;
     401:     addr->en_istat = EN_IEN|EN_GO;
     402: }
     403:
     404: /*
     405:  * Ethernet output routine.
     406:  * Encapsulate a packet of type family for the local net.
     407:  * Use trailer local net encapsulation if enough data in first
     408:  * packet leaves a multiple of 512 bytes of data in remainder.
     409:  */
     410: enoutput(ifp, m0, dst)
     411:     struct ifnet *ifp;
     412:     struct mbuf *m0;
     413:     struct sockaddr *dst;
     414: {
     415:     int type, dest, s, error;
     416:     register struct mbuf *m = m0;
     417:     register struct en_header *en;
     418:     register int off;
     419:
     420:     switch (dst->sa_family) {
     421:
     422: #ifdef INET
     423:     case AF_INET:
     424:         dest = ((struct sockaddr_in *)dst)->sin_addr.s_addr;
     425:         if (dest & 0x00ffff00) {
     426:             error = EPERM;      /* ??? */
     427:             goto bad;
     428:         }
     429:         dest = (dest >> 24) & 0xff;
     430:         off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len;
     431:         if (off > 0 && (off & 0x1ff) == 0 &&
     432:             m->m_off >= MMINOFF + 2 * sizeof (u_short)) {
     433:             type = ENPUP_TRAIL + (off>>9);
     434:             m->m_off -= 2 * sizeof (u_short);
     435:             m->m_len += 2 * sizeof (u_short);
     436:             *mtod(m, u_short *) = ENPUP_IPTYPE;
     437:             *(mtod(m, u_short *) + 1) = m->m_len;
     438:             goto gottrailertype;
     439:         }
     440:         type = ENPUP_IPTYPE;
     441:         off = 0;
     442:         goto gottype;
     443: #endif
     444: #ifdef PUP
     445:     case AF_PUP:
     446:         dest = ((struct sockaddr_pup *)dst)->spup_addr.pp_host;
     447:         type = ENPUP_PUPTYPE;
     448:         off = 0;
     449:         goto gottype;
     450: #endif
     451:
     452:     default:
     453:         printf("en%d: can't handle af%d\n", ifp->if_unit,
     454:             dst->sa_family);
     455:         error = EAFNOSUPPORT;
     456:         goto bad;
     457:     }
     458:
     459: gottrailertype:
     460:     /*
     461: 	 * Packet to be sent as trailer: move first packet
     462: 	 * (control information) to end of chain.
     463: 	 */
     464:     while (m->m_next)
     465:         m = m->m_next;
     466:     m->m_next = m0;
     467:     m = m0->m_next;
     468:     m0->m_next = 0;
     469:     m0 = m;
     470:
     471: gottype:
     472:     /*
     473: 	 * Add local net header.  If no space in first mbuf,
     474: 	 * allocate another.
     475: 	 */
     476:     if (m->m_off > MMAXOFF ||
     477:         MMINOFF + sizeof (struct en_header) > m->m_off) {
     478:         m = m_get(M_DONTWAIT);
     479:         if (m == 0) {
     480:             error = ENOBUFS;
     481:             goto bad;
     482:         }
     483:         m->m_next = m0;
     484:         m->m_off = MMINOFF;
     485:         m->m_len = sizeof (struct en_header);
     486:     } else {
     487:         m->m_off -= sizeof (struct en_header);
     488:         m->m_len += sizeof (struct en_header);
     489:     }
     490:     en = mtod(m, struct en_header *);
     491:     en->en_dhost = dest;
     492:     en->en_type = htons((u_short)type);
     493:
     494:     /*
     495: 	 * Queue message on interface, and start output if interface
     496: 	 * not yet active.
     497: 	 */
     498:     s = splimp();
     499:     if (IF_QFULL(&ifp->if_snd)) {
     500:         IF_DROP(&ifp->if_snd);
     501:         error = ENOBUFS;
     502:         goto qfull;
     503:     }
     504:     IF_ENQUEUE(&ifp->if_snd, m);
     505:     if (en_softc[ifp->if_unit].es_oactive == 0)
     506:         enstart(ifp->if_unit);
     507:     splx(s);
     508:     return (0);
     509: qfull:
     510:     m0 = m;
     511:     splx(s);
     512: bad:
     513:     m_freem(m0);
     514:     return (error);
     515: }
     516: #endif	NEN > 0

#### Defined functions

enattach defined in line 104; used 2 times

- in line 40-44(2)

encollide defined in line 255; used 2 times

- in line 40, 84

endocoll defined in line 266; used 2 times

- in line 232, 263

eninit defined in line 124; used 2 times

- in line 47, 114

enoutput defined in line 410; used 2 times

- in line 47, 115

enprobe defined in line 75; used 2 times

- in line 40-44(2)

enrint defined in line 303; used 2 times

- in line 40, 84

enstart defined in line 168; used 3 times

- in line 247, 286, 506

enxint defined in line 221; used 4 times

- in line 40, 84, 151, 278

#### Defined variables

en_softc defined in line 69; used 8 times

- in line 107, 127, 173, 225, 258, 269, 306, 505

enalldelay defined in line 156; used 1 times

- in line 202

endriver defined in line 43; never used
eninfo defined in line 41; used 5 times

- in line 44, 128, 172, 224, 307

enlastdel defined in line 157; used 1 times

- in line 203

enlastmask defined in line 158; used 1 times

- in line 204

enstd defined in line 42; used 1 times

- in line 44

pupdst defined in line 291; used 2 times

- in line 377-380(2)

pupproto defined in line 292; used 2 times

- in line 376-379(2)

pupsrc defined in line 290; used 2 times

- in line 378-379(2)

#### Defined struct's

en_softc defined in line 61; used 14 times

- in line 107(2), 127(2), 173(2), 225(2), 258(2), 269(2), 306(2)

#### Defined macros

ENMRU defined in line 38; used 5 times

- in line 133, 147, 331-333(2), 400

ENMTU defined in line 37; used 2 times

- in line 112, 340

ENUNIT defined in line 45; used 1 times

- in line 171

endataaddr defined in line 336; used 2 times

- in line 342-343(2)

Last modified: 1997-01-19 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1145 |