home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sys / tahoe / if / if_ace.c next >
Encoding:
C/C++ Source or Header  |  1991-05-08  |  19.3 KB  |  754 lines

  1. /*
  2.  * Copyright (c) 1988 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * This code is derived from software contributed to Berkeley by
  6.  * Computer Consoles Inc.
  7.  *
  8.  * Redistribution and use in source and binary forms, with or without
  9.  * modification, are permitted provided that the following conditions
  10.  * are met:
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  * 2. Redistributions in binary form must reproduce the above copyright
  14.  *    notice, this list of conditions and the following disclaimer in the
  15.  *    documentation and/or other materials provided with the distribution.
  16.  * 3. All advertising materials mentioning features or use of this software
  17.  *    must display the following acknowledgement:
  18.  *    This product includes software developed by the University of
  19.  *    California, Berkeley and its contributors.
  20.  * 4. Neither the name of the University nor the names of its contributors
  21.  *    may be used to endorse or promote products derived from this software
  22.  *    without specific prior written permission.
  23.  *
  24.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  25.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  28.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  29.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  30.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  31.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  33.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  34.  * SUCH DAMAGE.
  35.  *
  36.  *    @(#)if_ace.c    7.8 (Berkeley) 12/16/90
  37.  */
  38.  
  39. /*
  40.  * ACC VERSAbus Ethernet controller
  41.  */
  42. #include "ace.h"
  43. #if NACE > 0
  44.  
  45. #include "sys/param.h"
  46. #include "sys/systm.h"
  47. #include "sys/malloc.h"
  48. #include "sys/mbuf.h"
  49. #include "sys/buf.h"
  50. #include "sys/protosw.h"
  51. #include "sys/socket.h"
  52. #include "sys/vmmac.h"
  53. #include "sys/ioctl.h"
  54. #include "sys/errno.h"
  55. #include "sys/vmparam.h"
  56. #include "sys/syslog.h"
  57.  
  58. #include "net/if.h"
  59. #include "net/netisr.h"
  60. #include "net/route.h"
  61. #ifdef INET
  62. #include "netinet/in.h"
  63. #include "netinet/in_systm.h"
  64. #include "netinet/in_var.h"
  65. #include "netinet/ip.h"
  66. #include "netinet/ip_var.h"
  67. #include "netinet/if_ether.h"
  68. #endif
  69. #ifdef NS
  70. #include "netns/ns.h"
  71. #include "netns/ns_if.h"
  72. #endif
  73.  
  74. #include "../include/cpu.h"
  75. #include "../include/pte.h"
  76.  
  77. #include "../include/mtpr.h"
  78. #include "../if/if_acereg.h"
  79. #include "../vba/vbavar.h"
  80.  
  81. int    aceprobe(), aceattach(), acerint(), acecint(), acestart();
  82. struct    vba_device *aceinfo[NACE];
  83. long    acestd[] = { 0 };
  84. struct    vba_driver acedriver =
  85.     { aceprobe, 0, aceattach, 0, acestd, "ace", aceinfo, "v/eiu", 0 };
  86.  
  87. int    aceinit(), aceoutput(), aceioctl(), acereset();
  88. struct    mbuf *aceget();
  89.  
  90. /*
  91.  * Ethernet software status per interface.
  92.  *
  93.  * Each interface is referenced by a network interface structure,
  94.  * is_if, which the routing code uses to locate the interface.
  95.  * This structure contains the output queue for the interface, its address, ...
  96.  */
  97. struct    ace_softc {
  98.     struct    arpcom is_ac;        /* Ethernet common part    */
  99. #define    is_if    is_ac.ac_if        /* network-visible interface */
  100. #define    is_addr    is_ac.ac_enaddr        /* hardware Ethernet address */
  101.     short    is_flags;
  102. #define    ACEF_OACTIVE    0x1        /* output is active */
  103. #define    ACEF_RCVPENDING    0x2        /* start rcv in acecint    */
  104.     short    is_promiscuous;        /* true is enabled */
  105.     short    is_segboundry;        /* first TX Seg in dpm */
  106.     short    is_eictr;        /* Rx segment tracking ctr */
  107.     short    is_eoctr;        /* Tx segment tracking ctr */
  108.     short    is_txnext;        /* Next available Tx segment */
  109.     short    is_currnd;        /* current random backoff */
  110.     struct    ace_stats is_stats;    /* holds board statistics */
  111.     short    is_xcnt;        /* count xmitted segments to be acked 
  112.                        by the controller */
  113.     long    is_ivec;        /* autoconfig interrupt vector base */
  114.     struct    pte *is_map;        /* pte map for dual ported memory */
  115.     caddr_t    is_dpm;            /* address of mapped memory */
  116. } ace_softc[NACE];
  117. extern    struct ifnet loif;
  118.  
  119. aceprobe(reg, vi)
  120.     caddr_t reg;
  121.     struct vba_device *vi;
  122. {
  123.     register br, cvec;        /* must be r12, r11 */
  124.     struct acedevice *ap = (struct acedevice *)reg;
  125.     struct ace_softc *is = &ace_softc[vi->ui_unit];
  126.  
  127. #ifdef lint
  128.     br = 0; cvec = br; br = cvec;
  129.     acerint(0); acecint(0);
  130. #endif
  131.     if (badaddr(reg, 2))
  132.         return (0);
  133.     movow(&ap->csr, CSR_RESET);
  134.     DELAY(10000);
  135. #ifdef notdef
  136.     /*
  137.      * Select two spaces for the interrupts aligned to an
  138.      * eight vector boundary and fitting in 8 bits (as
  139.      * required by the controller) -- YECH.  The controller
  140.      * will be notified later at initialization time.
  141.      */
  142.     if ((vi->ui_hd->vh_lastiv -= 2) > 0xff)
  143.         vi->ui_hd->vh_lastiv  = 0x200;
  144.     is->is_ivec = vi->ui_hd->vh_lastiv = vi->ui_hd->vh_lastiv &~ 0x7;
  145. #else
  146.     is->is_ivec = 0x90+vi->ui_unit*8;
  147. #endif
  148.     br = 0x14, cvec = is->is_ivec;        /* XXX */
  149.     return (sizeof (*ap));
  150. }
  151.  
  152. /*
  153.  * Interface exists: make available by filling in network interface
  154.  * record.  System will initialize the interface when it is ready
  155.  * to accept packets.
  156.  */
  157. aceattach(ui)
  158.     struct vba_device *ui;
  159. {
  160.     register short unit = ui->ui_unit;
  161.     register struct ace_softc *is = &ace_softc[unit];
  162.     register struct ifnet *ifp = &is->is_if;
  163.     register struct acedevice *addr = (struct acedevice *)ui->ui_addr;
  164.     register short *wp, i;
  165.  
  166.     ifp->if_unit = unit;
  167.     ifp->if_name = "ace";
  168.     ifp->if_mtu = ETHERMTU;
  169.     /*
  170.      * Get station's addresses and set multicast hash table.
  171.      */
  172.     for (wp = (short *)addr->station, i = 0; i < 6; i++)
  173.         is->is_addr[i] = ~*wp++;
  174.     printf("ace%d: hardware address %s\n", unit,
  175.         ether_sprintf(is->is_addr));
  176.     is->is_promiscuous = 0;
  177.     for (wp = (short *)addr->hash, i =  0; i < 8; i++)
  178.         movow(wp++, ~0xf); 
  179.     movow(&addr->bcastena[0], ~0xffff); 
  180.     movow(&addr->bcastena[1], ~0xffff);
  181.     /*
  182.      * Allocate and map dual ported VERSAbus memory.
  183.      */
  184.     if (vbmemalloc(32, (caddr_t)ui->ui_flags,
  185.         &is->is_map, &is->is_dpm) == 0) {
  186.         printf("ace%d: can't allocate VERSAbus memory map\n", unit);
  187.         return;
  188.     }
  189.  
  190.     ifp->if_init = aceinit;
  191.     ifp->if_output = ether_output;
  192.     ifp->if_start = acestart;
  193.     ifp->if_ioctl = aceioctl;
  194.     ifp->if_reset = acereset;
  195.     ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
  196.     if_attach(ifp);
  197. }
  198.  
  199. /*
  200.  * Reset of interface after "system" reset.
  201.  */
  202. acereset(unit, vban)
  203.     int unit, vban;
  204. {
  205.     register struct vba_device *ui;
  206.  
  207.     if (unit >= NACE || (ui = aceinfo[unit]) == 0 || ui->ui_alive == 0 ||
  208.         ui->ui_vbanum != vban)
  209.         return;
  210.     printf(" ace%d", unit);
  211.     aceinit(unit);
  212. }
  213.  
  214. /*
  215.  * Initialization of interface; clear recorded pending operations
  216.  */
  217. aceinit(unit)
  218.     int unit;
  219. {
  220.     register struct ace_softc *is = &ace_softc[unit];
  221.     register struct vba_device *ui = aceinfo[unit];
  222.     register struct acedevice *addr;
  223.     register short Csr;
  224.     register int s;
  225.  
  226.     if (is->is_if.if_addrlist == (struct ifaddr *)0)
  227.         return;
  228.     if ((is->is_if.if_flags & IFF_RUNNING) == 0) {
  229.         /*
  230.          * Reset the controller, initialize the recieve buffers,
  231.          * and turn the controller on again and set board online.
  232.          */
  233.         addr = (struct acedevice *)ui->ui_addr;
  234.         s = splimp();
  235.         movow(&addr->csr, CSR_RESET);
  236.         DELAY(10000);
  237.  
  238.         /*
  239.          * Clean up dpm since the controller might
  240.          * jumble dpm after reset.
  241.          */
  242.         acesetup(unit);
  243.         movow(&addr->csr, CSR_GO);
  244.         Csr = addr->csr;
  245.         if (Csr & CSR_ACTIVE) {
  246.             movow(&addr->ivct, is->is_ivec);
  247.             Csr |= CSR_IENA | is->is_promiscuous;
  248.             movow(&addr->csr, Csr);
  249.             is->is_flags = 0;
  250.             is->is_xcnt = 0;
  251.             is->is_if.if_flags |= IFF_RUNNING;
  252.         }
  253.         splx(s);
  254.     }
  255.     if (is->is_if.if_snd.ifq_head)
  256.         acestart(&is->is_if);
  257. }
  258.  
  259. /*
  260.  * Start output on interface.
  261.  * Get another datagram to send off of the interface queue,
  262.  * and map it to the interface before starting the output.
  263.  */
  264. acestart(ifp)
  265.     register struct ifnet *ifp;
  266. {
  267.     register struct tx_segment *txs;
  268.     register long len;
  269.     register int s;
  270.     struct mbuf *m;
  271.     short retries;
  272. #define    is ((struct ace_softc *)ifp)
  273.  
  274. again:
  275.     txs = (struct tx_segment*)(is->is_dpm + (is->is_txnext << 11));
  276.     if (txs->tx_csr & TCS_TBFULL) {
  277.         is->is_stats.tx_busy++;
  278.         ifp->if_flags |= IFF_OACTIVE;
  279.         return (0);
  280.     }
  281.     s = splimp();
  282.     IF_DEQUEUE(&ifp->if_snd, m);
  283.     splx(s);
  284.     if (m == 0) {
  285.         ifp->if_flags &= ~IFF_OACTIVE;
  286.         return (0);
  287.     }
  288.     len = aceput(txs->tx_data, m);
  289.     retries = txs->tx_csr & TCS_RTC;
  290.     if (retries > 0)
  291.         acebakoff(is, txs, retries);
  292.  
  293.     /*
  294.      * Ensure minimum packet length.
  295.      * This makes the safe assumtion that there are no virtual holes
  296.      * after the data.
  297.      * For security, it might be wise to zero out the added bytes,
  298.      * but we're mainly interested in speed at the moment.
  299.      */
  300.     if (len - sizeof (struct ether_header) < ETHERMIN)
  301.         len = ETHERMIN + sizeof (struct ether_header);
  302.     if (++is->is_txnext > SEG_MAX) 
  303.         is->is_txnext = is->is_segboundry;
  304.     ifp->if_opackets++;
  305.     is->is_xcnt++;
  306.     len = (len & 0x7fff) | TCS_TBFULL;
  307.     movow(txs, len);
  308.     goto again;
  309. #undef is
  310. }
  311.  
  312. /*
  313.  * Transmit done interrupt.
  314.  */
  315. acecint(unit)
  316.     int unit;
  317. {
  318.     register struct ace_softc *is = &ace_softc[unit];
  319.     register struct tx_segment *txseg;
  320.     short eostat;
  321.  
  322.     if (is->is_xcnt <= 0)  {
  323.         log(LOG_ERR, "ace%d: stray xmit interrupt, xcnt %d\n",
  324.             unit, is->is_xcnt);
  325.         is->is_xcnt = 0;
  326.         if (is->is_if.if_snd.ifq_head)
  327.             acestart(&is->is_if);
  328.         return;
  329.     }
  330.     is->is_xcnt--;
  331.     txseg = (struct tx_segment *)((is->is_eoctr << 11) + is->is_dpm);
  332.     eostat = txseg->tx_csr;
  333.     if ((eostat & TCS_TBFULL) == 0) {
  334.         is->is_stats.tx_retries += eostat & TCS_RTC;
  335.         if (eostat & TCS_RTFAIL)  {
  336.             is->is_stats.tx_discarded++;
  337.             is->is_if.if_oerrors++;
  338.         } else 
  339.             is->is_stats.tx_datagrams++;
  340.         if (++is->is_eoctr >= 16)
  341.             is->is_eoctr = is->is_segboundry; 
  342.     } 
  343.     if (is->is_if.if_snd.ifq_head)
  344.         acestart(&is->is_if);
  345. }
  346.  
  347. /*
  348.  * Ethernet interface receiver interrupt.
  349.  * If input error just drop packet.
  350.  * Otherwise purge input buffered data path and examine 
  351.  * packet to determine type.  If can't determine length
  352.  * from type, then have to drop packet.  Othewise decapsulate
  353.  * packet based on type and pass to type specific higher-level
  354.  * input routine.
  355.  */
  356. acerint(unit)
  357.     int unit;
  358. {
  359.     register struct ace_softc *is = &ace_softc[unit];
  360.     register struct ifqueue *inq;
  361.     register struct ether_header *ace;
  362.     register struct rx_segment *rxseg;
  363.     int len, s, off, resid;
  364.     struct mbuf *m;
  365.     short eistat;
  366.  
  367.     if ((is->is_if.if_flags&IFF_RUNNING) == 0)
  368.         return;
  369. again:
  370.     rxseg = (struct rx_segment *)((is->is_eictr << 11) + is->is_dpm);
  371.     eistat = rxseg->rx_csr;
  372.     if ((eistat & RCS_RBFULL) == 0)
  373.         return;
  374.     is->is_if.if_ipackets++;
  375.     if (++is->is_eictr >= is->is_segboundry) 
  376.         is->is_eictr = 0;
  377.     len = eistat & RCS_RBC;
  378.     if ((eistat & (RCS_ROVRN | RCS_RCRC | RCS_RODD)) ||
  379.         len < ET_MINLEN || len > ET_MAXLEN+CRC_SIZE) {
  380.         if (eistat & RCS_ROVRN)
  381.             is->is_stats.rx_overruns++;
  382.         if (eistat & RCS_RCRC)
  383.             is->is_stats.rx_crc_errors++;
  384.         if (eistat & RCS_RODD)
  385.             is->is_stats.rx_align_errors++;
  386.         if (len < ET_MINLEN)
  387.             is->is_stats.rx_underruns++;
  388.         if (len > ET_MAXLEN+CRC_SIZE)
  389.             is->is_stats.rx_overruns++;
  390.         is->is_if.if_ierrors++;
  391.         rxseg->rx_csr = 0;
  392.         return;
  393.     } else
  394.         is->is_stats.rx_datagrams++;
  395.     ace = (struct ether_header *)rxseg->rx_data;
  396.     len -= sizeof (struct ether_header);
  397.     /*
  398.      * Deal with trailer protocol: if type is trailer
  399.      * get true type from first 16-bit word past data.
  400.      * Remember that type was trailer by setting off.
  401.      */
  402.     ace->ether_type = ntohs((u_short)ace->ether_type);
  403. #define    acedataaddr(ace, off, type) \
  404.     ((type)(((caddr_t)(((char *)ace)+sizeof (struct ether_header))+(off))))
  405.     if (ace->ether_type >= ETHERTYPE_TRAIL &&
  406.         ace->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {
  407.         off = (ace->ether_type - ETHERTYPE_TRAIL) * 512;
  408.         if (off >= ETHERMTU)
  409.             goto setup;        /* sanity */
  410.         ace->ether_type = ntohs(*acedataaddr(ace, off, u_short *));
  411.         resid = ntohs(*(acedataaddr(ace, off+2, u_short *)));
  412.         if (off + resid > len)
  413.             goto setup;        /* sanity */
  414.         len = off + resid;
  415.     } else
  416.         off = 0;
  417.     if (len == 0)
  418.         goto setup;
  419.  
  420.     /*
  421.      * Pull packet off interface.  Off is nonzero if packet
  422.      * has trailing header; aceget will then force this header
  423.      * information to be at the front.
  424.      */
  425.     m = aceget((u_char *)rxseg->rx_data, len, off, &is->is_if);
  426.     if (m)
  427.         ether_input(&is->is_if, ace, m);
  428. setup:
  429.     rxseg->rx_csr = 0;
  430.     goto again;
  431. }
  432.  
  433. /*
  434.  * Routine to copy from mbuf chain to transmit buffer on the VERSAbus
  435.  * If packet size is less than the minimum legal size,
  436.  * the buffer is expanded.  We probably should zero out the extra
  437.  * bytes for security, but that would slow things down.
  438.  */
  439. aceput(txbuf, m)
  440.     char *txbuf;
  441.     struct mbuf *m;
  442. #ifdef notdef
  443. {
  444.     register u_char *bp, *mcp;
  445.     register short *s1, *s2;
  446.     register u_int len;
  447.     register struct mbuf *mp;
  448.     int total;
  449.  
  450.     total = mp->m_pkthdr.len;
  451.     bp = (u_char *)txbuf;
  452.     for (mp = m; mp; mp = mp->m_next) {
  453.         len = mp->m_len;
  454.         if (len == 0)
  455.             continue;
  456.         mcp = mtod(mp, u_char *);
  457.         if (((int)mcp & 01) && ((int)bp & 01)) {
  458.             /* source & destination at odd addresses */
  459.             movob(bp++, *mcp++);
  460.             --len;
  461.         }
  462.         if (len > 1 && (((int)mcp & 01)==0) && (((int)bp & 01)==0)) {
  463.             int l = len & 1;
  464.  
  465.             s1 = (short *)bp;
  466.             s2 = (short *)mcp;
  467.             len >>= 1;        /* count # of shorts */
  468.             while (len-- != 0)
  469.                 movow(s1++, *s2++);
  470.             len = l;        /* # remaining bytes */
  471.             bp = (u_char *)s1;
  472.             mcp = (u_char *)s2;
  473.         }
  474.         while (len-- != 0)
  475.             movob(bp++, *mcp++);
  476.     }
  477.     m_freem(m);
  478.     return (total);
  479. }
  480. #else
  481. {
  482.     register u_char *bp, *mcp;
  483.     register short *s1, *s2;
  484.     register u_int len;
  485.     register struct mbuf *mp;
  486.     int total;
  487.  
  488.     total = 0;
  489.     bp = (u_char *)txbuf;
  490.     for (mp = m; (mp); mp = mp->m_next) {
  491.         len = mp->m_len;
  492.         if (len == 0)
  493.             continue;
  494.         total += len;
  495.         mcp = mtod(mp, u_char *);
  496.         if (((int)mcp & 01) && ((int)bp & 01)) {
  497.             /* source & destination at odd addresses */
  498.             movob(bp++, *mcp++);
  499.             --len;
  500.         }
  501.         if (len > 1 && (((int)mcp & 01)==0) && (((int)bp & 01)==0)) {
  502.             register u_int l;
  503.  
  504.             s1 = (short *)bp;
  505.             s2 = (short *)mcp;
  506.             l = len >> 1;        /* count # of shorts */
  507.             while (l-- != 0)
  508.                 movow(s1++, *s2++);
  509.             len &= 1;        /* # remaining bytes */
  510.             bp = (u_char *)s1;
  511.             mcp = (u_char *)s2;
  512.         }
  513.         while (len-- != 0)
  514.             movob(bp++, *mcp++);
  515.     }
  516.     m_freem(m);
  517.     return (total);
  518. }
  519. #endif
  520.  
  521. /*
  522.  * Routine to copy from VERSAbus memory into mbufs.
  523.  *
  524.  * Warning: This makes the fairly safe assumption that
  525.  * mbufs have even lengths.
  526.  */
  527. struct mbuf *
  528. aceget(rxbuf, totlen, off, ifp)
  529.     u_char *rxbuf;
  530.     int totlen, off;
  531.     struct ifnet *ifp;
  532. {
  533.     register u_char *cp, *mcp;
  534.     register struct mbuf *m;
  535.     register int tlen;
  536.     struct mbuf *top = 0, **mp = ⊤
  537.     int len;
  538.     u_char *packet_end;
  539.  
  540.     rxbuf += sizeof (struct ether_header);
  541.     cp = rxbuf;
  542.     packet_end = cp + totlen;
  543.     if (off) {
  544.         off += 2 * sizeof(u_short);
  545.         totlen -= 2 * sizeof(u_short);
  546.         cp = rxbuf + off;
  547.     }
  548.  
  549.     MGETHDR(m, M_DONTWAIT, MT_DATA);
  550.     if (m == 0)
  551.         return (0);
  552.     m->m_pkthdr.rcvif = ifp;
  553.     m->m_pkthdr.len = totlen;
  554.     m->m_len = MHLEN;
  555.  
  556.     while (totlen > 0) {
  557.         if (top) {
  558.             MGET(m, M_DONTWAIT, MT_DATA);
  559.             if (m == 0) {
  560.                 m_freem(top);
  561.                 return (0);
  562.             }
  563.             m->m_len = MLEN;
  564.         }
  565.         len = min(totlen, (packet_end - cp));
  566.         if (len >= MINCLSIZE) {
  567.             MCLGET(m, M_DONTWAIT);
  568.             if (m->m_flags & M_EXT)
  569.                 m->m_len = len = min(len, MCLBYTES);
  570.             else
  571.                 len = m->m_len;
  572.         } else {
  573.             /*
  574.              * Place initial small packet/header at end of mbuf.
  575.              */
  576.             if (len < m->m_len) {
  577.                 if (top == 0 && len + max_linkhdr <= m->m_len)
  578.                     m->m_data += max_linkhdr;
  579.                 m->m_len = len;
  580.             } else
  581.                 len = m->m_len;
  582.         }
  583.         mcp = mtod(m, u_char *);
  584.         /*bcopy((caddr_t)cp, (caddr_t)mcp, len);*/
  585.         /*cp += len; mcp += len;*/
  586.         tlen = len;
  587.         if (((int)mcp & 01) && ((int)cp & 01)) {
  588.             /* source & destination at odd addresses */
  589.             *mcp++ = *cp++;
  590.             --tlen;
  591.         }
  592.         if (tlen > 1 && (((int)mcp&01) == 0) && (((int)cp&01) == 0)) {
  593.             register short *s1, *s2;
  594.             register int l;
  595.  
  596.             s1 = (short *)mcp;
  597.             s2 = (short *)cp;
  598.             l = tlen >> 1;        /* count # of shorts */
  599.             while (l-- > 0)        /* copy shorts */
  600.                 *s1++ = *s2++;
  601.             tlen &= 1;        /* # remaining bytes */
  602.             mcp = (u_char *)s1;
  603.             cp = (u_char *)s2;
  604.         }
  605.         while (tlen-- > 0)
  606.             *mcp++ = *cp++;
  607.         *mp = m;
  608.         mp = &m->m_next;
  609.         totlen -= len;
  610.         if (cp == packet_end)
  611.             cp = rxbuf;
  612.     }
  613.     return (top);
  614. }
  615.  
  616. /* backoff table masks */
  617. short    random_mask_tbl[16] = {
  618.     0x0040, 0x00c0, 0x01c0, 0x03c0, 0x07c0, 0x0fc0, 0x1fc0, 0x3fc0,
  619.     0x7fc0, 0xffc0, 0xffc0, 0xffc0, 0xffc0, 0xffc0, 0xffc0, 0xffc0
  620. };
  621.  
  622. acebakoff(is, txseg, retries)
  623.     struct ace_softc *is;
  624.     struct tx_segment *txseg;
  625.     register int retries;
  626. {
  627.     register short *pBakNum, random_num;
  628.     short *pMask;
  629.  
  630.     pMask = &random_mask_tbl[0];
  631.     pBakNum = &txseg->tx_backoff[0];
  632.     while (--retries >= 0) {
  633.         random_num = (is->is_currnd = (is->is_currnd * 18741)-13849);
  634.         random_num &= *pMask++;
  635.         *pBakNum++ = random_num ^ (short)(0xff00 | 0x00fc);
  636.     }
  637. }
  638.  
  639. /*
  640.  * Process an ioctl request.
  641.  */
  642. aceioctl(ifp, cmd, data)
  643.     register struct ifnet *ifp;
  644.     int cmd;
  645.     caddr_t data;
  646. {
  647.     register struct ifaddr *ifa = (struct ifaddr *)data;
  648.     struct acedevice *addr;
  649.     int s = splimp(), error = 0;
  650.  
  651.     switch (cmd) {
  652.  
  653.     case SIOCSIFADDR:
  654.         ifp->if_flags |= IFF_UP;
  655.         switch (ifa->ifa_addr->sa_family) {
  656. #ifdef INET
  657.         case AF_INET:
  658.             aceinit(ifp->if_unit);    /* before arpwhohas */
  659.             ((struct arpcom *)ifp)->ac_ipaddr =
  660.                 IA_SIN(ifa)->sin_addr;
  661.             arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);
  662.             break;
  663. #endif
  664. #ifdef NS
  665.         case AF_NS: {
  666.             struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
  667.             struct ace_softc *is = &ace_softc[ifp->if_unit];
  668.  
  669.             if (!ns_nullhost(*ina)) {
  670.                 ifp->if_flags &= ~IFF_RUNNING;
  671.                 addr = (struct acedevice *)
  672.                     aceinfo[ifp->if_unit]->ui_addr;
  673.                 movow(&addr->csr, CSR_RESET);
  674.                 DELAY(10000);
  675.                 /* set station address & copy addr to arp */
  676.                 acesetaddr(ifp->if_unit, addr, 
  677.                     ina->x_host.c_host);
  678.             } else
  679.                 ina->x_host = *(union ns_host *)is->is_addr;
  680.             aceinit(ifp->if_unit);
  681.             break;
  682.         }
  683. #endif
  684.         default:
  685.             aceinit(ifp->if_unit);
  686.             break;
  687.         }
  688.         break;
  689.  
  690.     case SIOCSIFFLAGS:
  691.         if ((ifp->if_flags&IFF_UP) == 0 && ifp->if_flags&IFF_RUNNING) {
  692.             addr = (struct acedevice *)
  693.                 (aceinfo[ifp->if_unit]->ui_addr);
  694.             movow(&addr->csr, CSR_RESET);
  695.             ifp->if_flags &= ~IFF_RUNNING;
  696.         } else if (ifp->if_flags&IFF_UP &&
  697.             (ifp->if_flags&IFF_RUNNING) == 0)
  698.             aceinit(ifp->if_unit);
  699.         break;
  700.  
  701.     default:
  702.         error = EINVAL;
  703.     }
  704.     splx(s);
  705.     return (error);
  706. }
  707.  
  708. /*
  709.  * Set the on-board station address, then read it back
  710.  * to initialize the address used by ARP (among others).
  711.  */
  712. acesetaddr(unit, addr, station)
  713.     short unit;
  714.     struct acedevice *addr;
  715.     u_char *station;
  716. {
  717.     struct ace_softc *is = &ace_softc[unit];
  718.     register short *wp, i;
  719.  
  720.     for (wp = (short *)addr->station, i = 0; i < 6; i++)
  721.         movow(wp++, ~*station++); 
  722.     for (wp = (short *)addr->station, i = 0; i < 6; i++)
  723.         is->is_addr[i] = ~*wp++;
  724.     printf("ace%d: hardware address %s\n", unit,
  725.         ether_sprintf(is->is_addr));
  726. }
  727.  
  728. /*
  729.  * Setup the device for use.  Initialize dual-ported memory,
  730.  * backoff parameters, and various other software state.
  731.  */
  732. acesetup(unit)
  733.     int unit;
  734. {
  735.     register struct ace_softc *is = &ace_softc[unit];
  736.     register char *pData1;
  737.     register short i;
  738.     struct acedevice *addr;
  739.  
  740.     bzero(is->is_dpm, 16384*2);
  741.     is->is_currnd = 49123;
  742.     addr = (struct acedevice *)aceinfo[unit]->ui_addr;
  743.     is->is_segboundry = (addr->segb >> 11) & 0xf;
  744.     pData1 = is->is_dpm + (is->is_segboundry << 11);
  745.     for (i = SEG_MAX + 1 - is->is_segboundry; --i >= 0;) {
  746.         acebakoff(is, (struct tx_segment *)pData1, 15);
  747.         pData1 += sizeof (struct tx_segment);
  748.     }
  749.     is->is_eictr = 0;
  750.     is->is_eoctr = is->is_txnext = is->is_segboundry;
  751.     bzero((char *)&is->is_stats, sizeof (is->is_stats));
  752. }
  753. #endif
  754.