home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / ip / manage / snmp / kip / ie.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-01-17  |  18.2 KB  |  729 lines

  1. /*
  2.  *  Intel 82586 ethernet chip driver (ie = Intel Ethernet)
  3.  *
  4.  *  (c) 1984, Stanford Univ. SUMEX project.
  5.  *  May be used but not sold without permission.
  6.  *
  7.  *  (c) 1986, Kinetics, Inc.
  8.  *  May be used but not sold without permission.
  9.  *
  10.  */
  11.  
  12. #include "gw.h"
  13. #include "fp/pbuf.h"
  14. #include "ie.h"
  15. #include "ether.h"
  16. #include "ab.h"
  17. #include "fp/cmdmacro.h"
  18.  
  19. #ifdef SNMP
  20. #include "inet.h"
  21. #include "mib.h"
  22. #include "snmp_vars.h"
  23. #endif
  24.  
  25. extern char broadcastaddr[];
  26. extern struct pqueue *sendq;
  27. extern struct pqueue *pq;
  28. extern struct fp_promram pvars;
  29.  
  30. /*
  31.  * wait for scb command word to clear
  32.  *    After giving a command, the 82586 steals the bus
  33.  *    and proceeds to capture the command end execute
  34.  *    it. When execution is completed, it clears the
  35.  *    command word. In general, we only check that
  36.  *    the command word is clear before we issue a
  37.  *    new command.
  38.  */
  39. #define    WAIT_CMD() { \
  40.     while (scbptr->sc_cmd != 0) \
  41.         pvars.fpr_iestats->fpi_cmdbusy++; \
  42. }
  43.  
  44. /*
  45.  * if the receiver is in the suspended state, give it the resume
  46.  * command to get it in a state ready to receive Ethernet packets again.
  47.  */
  48. #define RESUME() { \
  49.     if ((scbptr->sc_status & SWAB(SC_RUS)) == SWAB(RUS_SUSP)) { \
  50.         WAIT_CMD(); \
  51.         scbptr->sc_cmd |= SWAB(RUC_RES); \
  52.         K_CA86(); \
  53.     } \
  54. }
  55.  
  56. #define ierstart()     WAIT_CMD(); \
  57.     rfdhead->fd_rbd = SWAB(LO16(rbdhead)); \
  58.     scbptr->sc_rlist = SWAB(LO16(rfdhead))
  59.  
  60.  
  61. /* transmit buffers */
  62. #define    NTBD        1    /* number of transmit buffers */
  63. struct t_bd tbd[NTBD];
  64.  
  65. /* receiver frame descriptors */
  66. #define    NRFD        2    /* number of receive frame descriptors */
  67. struct fdes rfd[NRFD];        /* receive frame descriptors */
  68. struct fdes *rfdhead;        /* first in the list */
  69. struct fdes *rfdtail;        /* end of the list */
  70.  
  71. #define    NRBD        2    /* number of receive buffers */
  72. struct   r_bd  rbd[NRBD];    /* receive buffers */
  73. struct   r_bd *rbdhead;        /* first in the list */
  74. struct   r_bd *rbdtail;        /* end of the list */
  75.  
  76. char    tactive;        /* transmit active */
  77.  
  78. #ifdef    STATS
  79. /* statistics */
  80. int    iespur;            /* count of spurious interrupts */
  81. int    iefalsexmit;        /* false transmit interrupt */
  82. int    eintr;            /* count of ethernet interrupts */
  83. int    iestuck;        /* count of stuck interrupts */
  84. int    oknotset;        /* count of times ok bit is not set */
  85. int    okbits;            /* bit settings last time ok not set */
  86. int    ieready;        /* count of times receive unit already READY */
  87. int    iefcnt;            /* count of times that no frame descrip left */
  88. int    iebuf;            /* count of times that no rbuf descrip left */
  89. int    norecbufs;        /* count of times there are no receive pbufs */
  90. #endif    STATS
  91.  
  92. struct  scb *scbptr;
  93. struct   cb *cbptr;
  94. struct fdes *fdptr;
  95.  
  96. struct cb xmit;            /* transmit command buffer */
  97. struct cb iasetup;        /* Ethernet address setup command buffer */
  98. struct cb ieconfig;        /* Ethernet configuration command buffer */
  99. #ifndef SMARTLINK
  100. int scbbase ;
  101. struct scb *scbaddr;
  102. struct cb *cmdaddr;
  103. struct fdes *fdesaddr;
  104. #endif
  105.  
  106. /*
  107.  * Ether slop factor.  Pbuf MAXDATA is 630, but (sizeof ether (14) +
  108.  * sizeof ip (20) + sizeof udp (8) + max lap (603)) = 645.  This means
  109.  * that max size appletalk packets from the ether were being lost.
  110.  * We adjust the receive point in the pbuf upwards by at least 15 bytes
  111.  * so these will fit.  Actually the real solution would be to increase
  112.  * MAXDATA to 1K or so, but (1) this is currently hardwired into the PROM;
  113.  * (2) KFPS is already tight on buffer memory.
  114.  */
  115. #define    ESLOP    20
  116.  
  117.  
  118. /*
  119.  * configure and ethernet address setup of the chip
  120.  */
  121. config()
  122. {
  123. #ifndef NOETHERXMIT
  124.     extern struct ifnet ifie, ifet;
  125. #endif
  126.     extern u_char etheraddr[];
  127.  
  128.     scbptr->sc_clist = SWAB(LO16(&ieconfig));
  129.     iecmd();    /* configure */
  130.  
  131.     /* ethernet address loaded to i85286 */
  132.      eaddrcopy(etheraddr, &iasetup.cb_param[0]);
  133.     scbptr->sc_clist = SWAB(LO16(&iasetup));
  134.     iecmd();    /* iasetup */
  135.  
  136. #ifndef NOETHERXMIT
  137.     /* set ether address in interface struct */
  138.      eaddrcopy(etheraddr, ifie.if_haddr);
  139.     /* And also in the ETHERTALK interface */
  140.     eaddrcopy(etheraddr, ifet.if_haddr);
  141. #endif
  142. }
  143.  
  144. /*
  145.  * Initialize the i82586 chip
  146.  */
  147. ie_init()
  148. {
  149.     register int ss;
  150.     register struct fdes *rfdp;
  151.     register struct    r_bd *rbdp;
  152.     struct pbuf *pp;
  153.     extern u_short ienet;
  154.  
  155. #ifndef SMARTLINK
  156.     scbbase = (int)&k_scb & 0xff0000;
  157.     ss = scbbase;
  158.     scbaddr = (struct scb *)(ss  + LO16(&k_scb));
  159.     cmdaddr = (struct cb *)(ss + LO16(&k_cb));
  160.     fdesaddr = (struct fdes *)(ss + LO16(&k_fdes));
  161. #endif
  162.  
  163.     /* initialize scb structure */
  164.     scbptr = SCBADDR;
  165.     /*
  166.      * normally CPU should never write the status word
  167.      * but 82586 'ors' bits into it so it should begin life blank
  168.      */
  169.     /* empty status */
  170.     scbptr->sc_status = SWAB(STAT_IDLE | CUS_IDLE | RUS_IDLE);
  171.     /* no commands */
  172.     scbptr->sc_cmd   = SWAB(ACK_NONE | CUC_NOP | RUC_NOP);
  173.     scbptr->sc_clist = SWAB(LO16(CMDADDR));
  174.     scbptr->sc_rlist = SWAB(LO16(FDESADDR));
  175.     /*
  176.      * these are fetched, incremented and replaced by 82586
  177.      *  without releasing the bus. they stick at 0xffff when full
  178.      */
  179.     scbptr->sc_crcerrs  = SWAB(0);
  180.     scbptr->sc_alnerrs  = SWAB(0);
  181.     scbptr->sc_rscerrs  = SWAB(0);
  182.     scbptr->sc_ovrnerrs = SWAB(0);
  183.  
  184.     /* initialize the receive frame descriptor block */
  185.     fdptr = FDESADDR;
  186.     fdptr->fd_status = SWAB(0);
  187.     fdptr->fd_stat2  = SWAB(0);
  188.     fdptr->fd_link   = SWAB(CB_NIL);
  189.     fdptr->fd_rbd    = SWAB(FD_NIL);
  190.     for (ss = 0; ss < 6; ss++) {
  191.         fdptr->fd_daddr[ss] = '\0';
  192.         fdptr->fd_saddr[ss] = '\0';
  193.     }
  194.     fdptr->fd_type   = SWAB(0);
  195.  
  196.     /* hardware reset and establish our scb as the one to use */
  197.     K_SET86(scbptr);
  198.  
  199.     /* configure and iasetup */
  200.     config();
  201.  
  202.     /* transmit buffer stuff is set up at compile time, except... */
  203.     xmit.cb_param[0]  = SWAB(LO16(&tbd[0]));
  204.     tbd[0].tpbuf = 0;
  205.     scbptr->sc_clist  = SWAB(LO16(&xmit));
  206.  
  207.     /*
  208.      * setup receiver structures
  209.      */
  210.     for (rfdp = &rfd[0] ; rfdp < &rfd[NRFD] ; rfdp++ ) {
  211.         rfdp->fd_link = SWAB(LO16(rfdp+1));
  212.         rfdp->fd_rbd  = SWAB(FD_NIL);
  213. #ifndef FASTRECV
  214.         rfdp->fd_stat2 = SWAB(FD_S);
  215. #else
  216.         rfdp->fd_stat2 = 0;
  217. #endif
  218.     }
  219.     rfdp--;
  220.     rfdtail = rfdp;
  221.     rfdp->fd_stat2 |= SWAB(FD_EL);
  222.     rfdp->fd_link = SWAB(LO16(&rfd[0]));
  223.     rfdhead = rfdp = &rfd[0];
  224.     rfdp->fd_rbd = SWAB(LO16(&rbd[0]));
  225.     for (rbdp = &rbd[0]; rbdp < &rbd[NRBD]; rbdp++) {
  226.         /* get a buffer from the free list */
  227.         /* should already be at highest priority */
  228.         K_PGET(PT_ERBF,pp);
  229.         rbdp->rbd.bd_next  = SWAB(LO16(rbdp + 1));
  230.         rbdp->rpbuf = pp;
  231.         if (pp) {
  232.             /* make the pbuf into an Ethernet receive buffer */
  233.             rbdp->rbd.bd_buf   = SWAB(LO16(&pp->p_data[-ESLOP]));
  234.             rbdp->rbd.bd_bufhi = SWAB(HI16(&pp->p_data[-ESLOP]));
  235.             rbdp->rbd.bd_size  = SWAB(MAXDATA+ESLOP);
  236.         }
  237.     }
  238.     rbdp--;
  239.     rbdtail = rbdp;
  240.     rbdp->rbd.bd_next = SWAB(LO16(&rbd[0]));
  241.     rbdp->rbd.bd_size |= SWAB(BD_EL);
  242.     rbdhead = &rbd[0];
  243.     scbptr->sc_rlist = SWAB(LO16(&rfd[0]));
  244.     scbptr->sc_cmd = SWAB(ACK_CX | ACK_CNA | ACK_FR | ACK_RNR);
  245.     K_CA86();
  246.  
  247.     WAIT_CMD();    /* wait until chip is completely ready */
  248.     /* send 1st receive cmd */
  249.     ierstart();
  250.     scbptr->sc_cmd = SWAB(RUC_START);
  251.     K_CA86();
  252. }
  253.  
  254. /*
  255.  * Handle Ethernet interrupt.
  256.  */
  257. ieintr()
  258. {
  259.     register short scbstatus;
  260.     register short scbcmd;
  261.     extern struct ifnet ifie;
  262.  
  263.  
  264.     scbstatus = scbptr->sc_status;
  265.     scbcmd = SWAB(ACK_NONE | CUC_NOP | RUC_NOP);
  266.  
  267.     /* resume the receive unit if necessary */
  268.     RESUME();
  269.  
  270. #ifdef    STATS
  271.     eintr++;
  272.     if ((scbstatus & SWAB(STAT_FR | STAT_CX)) == 0) {
  273.         /* spurious interrupt */
  274.         iespur++;
  275.     }
  276. #endif    STATS
  277.     if ((scbstatus & SWAB(STAT_RNR))&&(rfdhead->fd_status & SWAB(FD_B))) {
  278.         register struct r_bd *rbdp;
  279.         /*
  280.          * Receiver not ready, yet still busy on 1st frame!
  281.          * This is a bogus packet of 'infinite' length
  282.          * and all ones.  Restart the RU.
  283.          *
  284.          * 4/29/86 - experiments indicate that this never
  285.          * happened in numerous startings of the gateway
  286.          * and over 250,000 packets. leftover from the original
  287.          * Croft Seagate code, and still included anyway -tim
  288.          */
  289.         for (rbdp = OTOA(struct r_bd *, rfdhead->fd_rbd);
  290.              rbdp->rbd.bd_count & SWAB(BD_F);
  291.              rbdp = OTOA(struct r_bd *, rbdp->rbd.bd_next)) {
  292.             rbdp->rbd.bd_count = SWAB(0);
  293.         }
  294. #ifdef    STATS
  295.         iestuck++;
  296. #endif    STATS
  297.         ierstart();
  298.         scbcmd = SWAB(ACK_RNR | RUC_START);
  299.     }
  300. #ifndef NOETHERXMIT
  301.     if (scbstatus & SWAB(STAT_CX)) {
  302.         /* interrupt after command (transmit) executed */
  303.         if ((tactive == 0) ||
  304.                 ((xmit.cb_status & SWAB(CB_COMPLETE)) == 0)) {
  305. #ifdef    STATS
  306.             /* false transmit interrupt */
  307.             iefalsexmit++;
  308. #endif    STATS
  309.         } else {
  310.             if ((xmit.cb_status & SWAB(CB_OK)) == 0) {
  311.                 /* increment total number of output errors */
  312.                 pvars.fpr_iestats->fpi_oerrors++;
  313.             }
  314.             /* increment total number of output packets */
  315.             pvars.fpr_iestats->fpi_opackets++;
  316.  
  317.             /* put the transmitted buffer back on the free list */
  318.             K_PFREE(tbd[0].tpbuf);
  319.             tbd[0].tpbuf = 0;
  320.             tactive = 0;
  321.             scbcmd |= scbstatus & SWAB(ACK_CX | ACK_CNA);
  322.             if (sendq->pq_head) {
  323.                 /* more on queue, restart output */
  324.                 iexstart();
  325.                 scbcmd |= SWAB(CUC_START);
  326.             }
  327.         }
  328.     }
  329. #endif
  330.     if (scbstatus & SWAB(STAT_FR)) {
  331.         /* get received frames if any */
  332.         ieframein();
  333.         ierstart();    /* start the receiver and ack */
  334.         scbcmd |= (scbstatus & SWAB(ACK_FR | ACK_RNR))|SWAB(RUC_START);
  335.     }
  336.     K_CLRINT();    /* clear interrupt flag */
  337.     scbptr->sc_cmd = scbcmd;
  338.     K_CA86();    /* ack current interrupts, start cmds if any */
  339.     if ((rfdhead->fd_status & SWAB(FD_C)) && (scbstatus & SWAB(STAT_FR))) {
  340.         /* more frames were received since we last checked */
  341.         /* we might have just acked them... better get them again */
  342.         ieframein();
  343.     }
  344. }
  345.  
  346. /*
  347.  * receive some Ethernet packet frames
  348.  */
  349. ieframein()
  350. {
  351.     register struct fdes *rfdp;
  352.     register struct r_bd *rbdp;
  353.     struct pbuf *pp;
  354.     struct pbuf *tp;
  355.     u_char *cp;
  356.     int free, count;
  357.     short pri;
  358.  
  359.     for (rfdp = rfdhead; rfdp->fd_status & SWAB(FD_C);
  360.             rfdp = rfdhead = OTOA(struct fdes *, rfdp->fd_link)) {
  361.  
  362.         /* resume the receive unit if necessary */
  363.         RESUME();
  364. #ifdef    STATS
  365.         if ((rfdp->fd_status & SWAB(FD_OK)) == 0) {
  366.             oknotset++;
  367.             okbits = SWAB(rfdp->fd_status);
  368.         }
  369. #endif    STATS
  370.         free = MAXDATA+ESLOP;
  371.         /* get a buffer from the free list */
  372.         K_PGET(PT_ERBF,pp);
  373.         /* get the relevant receive buffer descriptor */
  374.         rbdp = OTOA(struct r_bd *, rfdp->fd_rbd);
  375.         /* get the pbuf allocated to that rbuf descriptor */
  376.         tp = rbdp->rpbuf;
  377.         /* attach the new pbuf to the receive buffer descriptor */
  378.         rbdp->rpbuf = pp;
  379.         if (pp) {
  380.             rbdp->rbd.bd_buf   = SWAB(LO16(&pp->p_data[-ESLOP]));
  381.             rbdp->rbd.bd_bufhi = SWAB(HI16(&pp->p_data[-ESLOP]));
  382.             rbdp->rbd.bd_size  = SWAB(MAXDATA+ESLOP);
  383.         }
  384.         /* handle the packet just arrived, already in the pbuf */
  385.         pp = tp;
  386.         if (pp) {
  387.             pp->p_type = PT_ENET;
  388.             /* adjust counts of buffer types */
  389.             pvars.fpr_bufs->fpb_pbntypes[PT_ERBF]--;
  390.             pvars.fpr_bufs->fpb_pbntypes[PT_ENET]++;
  391.             pp->p_off = &pp->p_data[-ESLOP];
  392.             /* get the number of bytes received */
  393. /*            count = SWAB(rbdp->rbd.bd_count & SWAB(BD_COUNT)); */
  394.                 count = rbdp->rbd.bd_count;
  395.             count = SWAB(count) & BD_COUNT;
  396.             /* where to copy any additional pbuf's captured */
  397.             cp = &pp->p_data[count-ESLOP];
  398.             free -= count;
  399.         } else {
  400. #ifdef    STATS
  401.             ++norecbufs;
  402. #endif    STATS
  403. #ifdef SNMP
  404.             mib_ifEntry[0].ifInDiscards++;
  405. #endif SNMP
  406.         }
  407.         /* is that the only receive buffer descriptor this frame? */
  408.         if ((rbdp->rbd.bd_count & SWAB(BD_EOF)) == 0) {
  409.             /* more receive buffers in this frame, so... */
  410.             rbdp->rbd.bd_count = SWAB(0);
  411.             /* foreach additional rbuf descriptor with valid data */
  412.             for (rbdp = OTOA(struct r_bd *, rbdp->rbd.bd_next) ;
  413.              rbdp->rbd.bd_count & SWAB(BD_F) ;
  414.              rbdp = OTOA(struct r_bd *, rbdp->rbd.bd_next))
  415.             {
  416. /*            count = SWAB(rbdp->rbd.bd_count & SWAB(BD_COUNT)); */
  417.                 count = rbdp->rbd.bd_count;
  418.             count = SWAB(count) & BD_COUNT;
  419.             if (count <= free) {
  420.                 if (pp)
  421.                     bcopy(rbdp->rpbuf->p_data, cp, count);
  422.                 cp += count;
  423.                 free -= count;
  424.             } else {    /* buffer overflow */
  425. #ifndef NOETHERXMIT
  426.                 if (pp) {
  427.                     /* put buffer back on the free list */
  428.                     K_PFREE(pp);
  429.                     pp = 0;
  430.                     /* increment number of input errors */
  431.                     pvars.fpr_iestats->fpi_ierrors++;
  432.                 }
  433. #endif
  434.             }
  435.             if (rbdp->rbd.bd_count & SWAB(BD_EOF))
  436.                 break;
  437.             rbdp->rbd.bd_count = SWAB(0);
  438.             }
  439.         }
  440.         rbdp->rbd.bd_count = SWAB(0);
  441.         rbdp->rbd.bd_size |= SWAB(BD_EL);
  442.         /* link this last used rbuf to the end of the list */
  443.         rbdtail->rbd.bd_size &= SWAB(BD_COUNT); /* clear previous EL */
  444.         rbdtail = rbdp;
  445.         rbdhead = OTOA(struct r_bd *, rbdp->rbd.bd_next);
  446.         /* increment total number of input packets */
  447.         pvars.fpr_iestats->fpi_ipackets++;
  448.         if (pp) {
  449.             K_SPLIMP(&pri);
  450.             pp->p_len = (MAXDATA + ESLOP) - free;
  451. #ifdef notdef
  452.             p_if(pp) = &ifie;
  453. #endif
  454.             /* enqueue a buffer to the rec'd packet queue */
  455.             K_PENQNP(pq,pp);
  456.             K_SPLX(&pri);
  457.         }
  458.         rfdp->fd_status = SWAB(0);
  459. #ifndef FASTRECV
  460.         rfdp->fd_stat2 = SWAB(FD_EL | FD_S);
  461. #else
  462.         rfdp->fd_stat2 = SWAB(FD_EL);
  463. #endif
  464.         rfdp->fd_rbd = SWAB(FD_NIL);
  465. #ifndef FASTRECV
  466.         rfdtail->fd_stat2 = SWAB(FD_S);    /* clear previous FD_EL */
  467. #else
  468.         rfdtail->fd_stat2 = 0;    /* clear previous FD_EL */
  469. #endif
  470.         rfdtail = rfdp;
  471.     }
  472. }
  473.  
  474. /*
  475.  * Start or restart output.
  476.  */
  477. iexstart()
  478. {
  479. #ifndef NOETHERXMIT
  480.     register struct pbuf *p;
  481.  
  482.     if (sendq->pq_head == 0) {
  483.         sendf("leave iexstart() early");
  484.         return;        /* nothing in output queue */
  485.     }
  486.     /* dequeue a buffer from the Ethernet transmit queue */
  487.     K_PDEQNP(sendq,p);
  488.  
  489.     if (p->p_len < 60)
  490.         p->p_len = 60;
  491.     tbd[0].tbd.bd_count = SWAB(p->p_len | BD_EOF);
  492.     tbd[0].tbd.bd_buf   = SWAB(LO16(p->p_off));
  493.     tbd[0].tbd.bd_bufhi = SWAB(HI16(p->p_off));
  494.     tbd[0].tpbuf = p;
  495.     pvars.fpr_bufs->fpb_pbntypes[PT_ETBF]++;
  496.     pvars.fpr_bufs->fpb_pbntypes[p->p_type]--;
  497.     p->p_type = PT_ETBF;
  498.  
  499.     tactive = 1;
  500.     WAIT_CMD();
  501. #endif
  502. }
  503.     
  504. /*
  505.  * Execute a single command
  506.  *    command structure is already pointed at by scbptr->sc_clist
  507.  */
  508. iecmd()
  509. {
  510.     WAIT_CMD();
  511.     scbptr->sc_cmd = SWAB(ACK_NONE | CUC_START);
  512.     K_CA86();    /* pull channel attention */
  513.  
  514.     /* wait for indication of completion */
  515.     WAIT_CMD();
  516.     while ((scbptr->sc_status & SWAB(STAT_CNA)) == 0);
  517.     /* ack to clear interrupt */
  518.     scbptr->sc_cmd = scbptr->sc_status & SWAB(ACK_CX | ACK_CNA);
  519.     K_CA86();    /* pull channel attention */
  520. }
  521.  
  522. /*
  523.  * Start receiver, if needed.
  524.  */
  525. #ifndef ierstart
  526. ierstart()
  527. {
  528.     /* ignore if RU already running or less than 2 elements on lists */
  529.     if ((scbptr->sc_status & SWAB(SC_RUS)) == RUS_READY) {
  530. #ifdef    STATS
  531.         ieready++;
  532. #endif    STATS
  533.         return;
  534.     }
  535.     if (rfdhead->fd_stat2 & SWAB(FD_EL)) {
  536. #ifdef    STATS
  537.         iefcnt++;
  538. #endif    STATS
  539.         return;
  540.     }
  541.     if (rbdhead->rbd.bd_size & SWAB(BD_EL)) {
  542. #ifdef    STATS
  543.         iebuf++;
  544. #endif    STATS
  545.         return;
  546.     }
  547.     WAIT_CMD();
  548.     rfdhead->fd_rbd = SWAB(LO16(rbdhead));
  549.     scbptr->sc_rlist = SWAB(LO16(rfdhead));
  550. }
  551. #endif ierstart
  552.  
  553. #ifndef NOETHERXMIT
  554. /*
  555.  * Ethernet output routine.
  556.  * Encapsulate a packet of type af for the local net.
  557.  */
  558. ieoutput(ifp, p, af, dst)
  559. struct ifnet *ifp;
  560. struct pbuf *p;
  561. u_char *dst;
  562. {
  563.     short pri;
  564.     int type;
  565.     u_char edst[6];
  566.     iaddr_t idst;
  567.     register struct ether_header *eh;
  568.     struct LAP *lap;
  569.     extern u_char etheraddr[];
  570.     extern struct ifnet ifet;
  571.  
  572.     switch (af) {
  573.         /* Here for Ethertalk */
  574.         case AF_SDDP:
  575.         case AF_DDP:
  576.         if (ifp->if_dnode == 0)
  577.             goto drop;     /* don't know who we are yet */
  578.  
  579.         idst = 0L;
  580.         ((char *)(&idst))[3] = *dst;
  581.         if (!arpresolve(ifp, p, &idst, edst))
  582.             return (0);    /* if not yet resolved */
  583.         lap = (struct LAP *)p->p_off;
  584.         lap->src = ifp->if_dnode;
  585.         lap->dst = *dst;
  586.         lap->type = (af == AF_DDP) ? lapDDP : lapShortDDP;
  587.         type = ETHERTYPE_ETHERTALK;
  588.         break;
  589.  
  590. #ifdef notdef
  591.         case AF_LINK:
  592.         lap = (struct LAP *)p->p_off;
  593.         lap->src = ifp->if_dnode;
  594.         eaddrcopy(dst, edst);
  595.         type = (ETHERTYPE_ATALKTYPE);
  596.         break;
  597.  
  598.         case AF_RTMP:
  599.         if (ifp->if_dnode == 0)
  600.             goto drop;     /* don't know who we are yet */
  601.         lap = (struct LAP *)p->p_off;
  602.         lap->src = ifp->if_dnode;
  603.         lap->dst = 0xff;
  604.         lap->type = lapShortDDP;
  605.         eaddrcopy(dst, edst);
  606.         type = ETHERTYPE_ETHERTALK;
  607.         break;
  608. #endif
  609.  
  610.         case AF_ARP:
  611.         eaddrcopy(dst, edst);
  612.         type = ifp == &ifet ? ETHERTYPE_AARPTYPE : ETHERTYPE_ARPTYPE;
  613.         break;
  614.  
  615. #ifdef    IGP
  616.         case AF_PUP:
  617.         bcopy((caddr_t)dst, (caddr_t)edst, hln);
  618.         type = ETHERTYPE_PUPTYPE;
  619.         break;
  620. #endif    IGP
  621.  
  622.         case AF_IP:
  623.         idst = *(iaddr_t *)dst;
  624.         if (!arpresolve(ifp, p, &idst, edst))
  625.             return (0);    /* if not yet resolved */
  626.         type = ETHERTYPE_IPTYPE;
  627.         break;
  628.  
  629.         default:
  630. #ifdef SNMP
  631.         /* in case panic calls snmp_trap() */
  632.         mib_ifEntry[0].ifOutErrors++;
  633. #endif
  634.         panic("ie%d: can't handle af%d", ifp->if_unit, af);
  635.     }
  636.  
  637.     /*
  638.      * Add local net header.
  639.      */
  640.     p->p_off -= sizeof (struct ether_header);
  641.     p->p_len += sizeof (struct ether_header);
  642.     eh = (struct ether_header *)p->p_off;
  643.     eh->ether_type = htons((u_short)type);
  644.     eaddrcopy(edst, &eh->ether_dhost);
  645.     eaddrcopy(etheraddr, &eh->ether_shost);
  646. #ifdef SNMP
  647.     mib_ifEntry[0].ifOutOctets += ((p->p_len < 60) ? 60 : p->p_len);
  648.     if (eh->ether_dhost.ether_addr_octet[0] & 0x1)
  649.         mib_ifEntry[0].ifOutNUcastPkts++;
  650.     else
  651.         mib_ifEntry[0].ifOutUcastPkts++;
  652. #endif
  653.  
  654.     /*
  655.      * Queue message on interface, and start output if interface
  656.      * not yet active.
  657.      */
  658.     K_SPLIE(&pri);
  659.     /* enqueue a buffer to the Ethernet transmit queue */
  660.     K_PENQNP(sendq,p);
  661.     if (tactive == 0) {
  662.         iexstart();
  663.         scbptr->sc_cmd = SWAB(CUC_START);
  664.         K_CA86();    /* send transmit cmd */
  665.     }
  666.     K_SPLX(&pri);
  667.     return (0);
  668. drop:
  669.     /* put the buffer back on the free list */
  670.     K_PFREE(p);
  671.     return(-1);
  672. }
  673. #else
  674. ieoutput()
  675. {
  676. }
  677. #endif
  678.  
  679.  
  680. #ifdef    STATS
  681. /*
  682.  * Print Ethernet statistics
  683.  */
  684. ieprintstats()
  685. {
  686.     K_WAIT(20);
  687.     sendf(
  688.     "ethernet stats: in %d, out %d, inerrs %d, outerrs %d, norbufs %d",
  689.         pvars.fpr_iestats->fpi_ipackets,
  690.         pvars.fpr_iestats->fpi_opackets,
  691.         pvars.fpr_iestats->fpi_ierrors,
  692.         pvars.fpr_iestats->fpi_oerrors,
  693.         norecbufs);
  694.     K_WAIT(20);
  695.     sendf(
  696.     "spurious %d, false xmit %d, int count %d", iespur, iefalsexmit, eintr);
  697.     K_WAIT(20);
  698.     sendf("stuck %d, ok not set %d-0x%x", iestuck, oknotset, okbits);
  699.     K_WAIT(20);
  700.     sendf("ready %d, frame %d, buf %d, cmdbusy %d",
  701.         ieready, iefcnt, iebuf, pvars.fpr_iestats->fpi_cmdbusy);
  702.     K_WAIT(20);
  703.     sendf("scb status 0x%x, errs crc: %d, aln %d, rsc %d, ovrn %d",
  704.             SWAB(scbptr->sc_status), SWAB(scbptr->sc_crcerrs),
  705.             SWAB(scbptr->sc_alnerrs), SWAB(scbptr->sc_rscerrs),
  706.             SWAB(scbptr->sc_ovrnerrs));
  707. }
  708.  
  709. struct cb iedump;
  710. char dumpbuf[256];
  711.  
  712. /* dumps internal 82586 registers */
  713. dump()
  714. {
  715.     iedump.cb_cmd = SWAB(CB_EL|CBC_DUMP);
  716.     iedump.cb_param[0] = SWAB(LO16(dumpbuf));
  717.     scbptr->sc_clist = SWAB(LO16(&iedump));
  718.     iecmd();    /* dump */
  719.     sendf("dump results (7E): %x %x %x %x %x %x",dumpbuf[0x7e],
  720.         dumpbuf[0x7f], dumpbuf[0x80],dumpbuf[0x81],
  721.         dumpbuf[0x82],dumpbuf[0x83]);
  722.     /* set up for transmit command again */
  723.     scbptr->sc_clist  = SWAB(LO16(&xmit));
  724.     ierstart();    /* kick the receiver */
  725.     scbptr->sc_cmd = SWAB(RUC_START);
  726.     K_CA86();    /* start receives unit again, in case it stopped */
  727. }
  728. #endif    STATS
  729.