root/dev/isa/if_eg.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. egprintpcb
  2. egprintstat
  3. egoutPCB
  4. egreadPCBstat
  5. egreadPCBready
  6. egwritePCB
  7. egreadPCB
  8. egprobe
  9. egattach
  10. eginit
  11. egrecv
  12. egstart
  13. egintr
  14. egread
  15. egget
  16. egioctl
  17. egreset
  18. egwatchdog
  19. egstop

    1 /*      $OpenBSD: if_eg.c,v 1.30 2007/01/07 15:15:58 miod Exp $ */
    2 /*      $NetBSD: if_eg.c,v 1.26 1996/05/12 23:52:27 mycroft Exp $       */
    3 
    4 /*
    5  * Copyright (c) 1993 Dean Huxley <dean@fsa.ca>
    6  * All rights reserved.
    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 Dean Huxley.
   19  * 4. The name of Dean Huxley may not be used to endorse or promote products
   20  *    derived from this software without specific prior written permission.
   21  *
   22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   23  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   24  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   25  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   27  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   29  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   31  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   32  */
   33 /*
   34  * Support for 3Com 3c505 Etherlink+ card.
   35  */
   36 
   37 /* To do:
   38  * - multicast
   39  * - promiscuous
   40  */
   41 #include "bpfilter.h"
   42 
   43 #include <sys/types.h>
   44 #include <sys/param.h>
   45 #include <sys/mbuf.h>
   46 #include <sys/socket.h>
   47 #include <sys/ioctl.h>
   48 #include <sys/errno.h>
   49 #include <sys/syslog.h>
   50 #include <sys/systm.h>
   51 #include <sys/selinfo.h>
   52 #include <sys/device.h>
   53 
   54 #include <net/if.h>
   55 #include <net/if_dl.h>
   56 #include <net/if_types.h>
   57 #include <net/netisr.h>
   58 
   59 #ifdef INET
   60 #include <netinet/in.h>
   61 #include <netinet/in_systm.h>
   62 #include <netinet/in_var.h>
   63 #include <netinet/ip.h>
   64 #include <netinet/if_ether.h>
   65 #endif
   66 
   67 #if NBPFILTER > 0
   68 #include <net/bpf.h>
   69 #endif
   70 
   71 #include <machine/cpu.h>
   72 #include <machine/intr.h>
   73 
   74 #include <dev/isa/isavar.h>
   75 #include <dev/isa/if_egreg.h>
   76 #include <dev/isa/elink.h>
   77 
   78 /* for debugging convenience */
   79 #ifdef EGDEBUG
   80 #define DPRINTF(x) printf x
   81 #else
   82 #define DPRINTF(x)
   83 #endif
   84 
   85 #define EG_INLEN        10
   86 #define EG_BUFLEN       0x0670
   87 
   88 /*
   89  * Ethernet software status per interface.
   90  */
   91 struct eg_softc {
   92         struct device sc_dev;
   93         void *sc_ih;
   94         bus_space_tag_t sc_bst;
   95         bus_space_handle_t sc_bsh;
   96         struct arpcom sc_arpcom;        /* Ethernet common part */
   97         u_char  eg_rom_major;           /* Cards ROM version (major number) */ 
   98         u_char  eg_rom_minor;           /* Cards ROM version (minor number) */ 
   99         short   eg_ram;                 /* Amount of RAM on the card */
  100         u_char  eg_pcb[64];             /* Primary Command Block buffer */
  101         u_char  eg_incount;             /* Number of buffers currently used */
  102         u_char  *eg_inbuf;              /* Incoming packet buffer */
  103         u_char  *eg_outbuf;             /* Outgoing packet buffer */
  104 };
  105 
  106 int egprobe(struct device *, void *, void *);
  107 void egattach(struct device *, struct device *, void *);
  108 
  109 struct cfattach eg_ca = {
  110         sizeof(struct eg_softc), egprobe, egattach
  111 };
  112 
  113 struct cfdriver eg_cd = {
  114         NULL, "eg", DV_IFNET
  115 };
  116 
  117 int egintr(void *);
  118 void eginit(struct eg_softc *);
  119 int egioctl(struct ifnet *, u_long, caddr_t);
  120 void egrecv(struct eg_softc *);
  121 void egstart(struct ifnet *);
  122 void egwatchdog(struct ifnet *);
  123 void egreset(struct eg_softc *);
  124 void egread(struct eg_softc *, caddr_t, int);
  125 struct mbuf *egget(struct eg_softc *, caddr_t, int);
  126 void egstop(struct eg_softc *);
  127 
  128 static __inline void egprintpcb(struct eg_softc *);
  129 static __inline void egprintstat(u_char);
  130 static int egoutPCB(struct eg_softc *, u_char);
  131 static int egreadPCBstat(struct eg_softc *, u_char);
  132 static int egreadPCBready(struct eg_softc *);
  133 static int egwritePCB(struct eg_softc *);
  134 static int egreadPCB(struct eg_softc *);
  135 
  136 /*
  137  * Support stuff
  138  */
  139         
  140 static __inline void
  141 egprintpcb(sc)
  142         struct eg_softc *sc;
  143 {
  144         int i;
  145         
  146         for (i = 0; i < sc->eg_pcb[1] + 2; i++)
  147                 DPRINTF(("pcb[%2d] = %x\n", i, sc->eg_pcb[i]));
  148 }
  149 
  150 
  151 static __inline void
  152 egprintstat(b)
  153         u_char b;
  154 {
  155         DPRINTF(("%s %s %s %s %s %s %s\n", 
  156             (b & EG_STAT_HCRE)?"HCRE":"",
  157             (b & EG_STAT_ACRF)?"ACRF":"",
  158             (b & EG_STAT_DIR )?"DIR ":"",
  159             (b & EG_STAT_DONE)?"DONE":"",
  160             (b & EG_STAT_ASF3)?"ASF3":"",
  161             (b & EG_STAT_ASF2)?"ASF2":"",
  162             (b & EG_STAT_ASF1)?"ASF1":""));
  163 }
  164 
  165 static int
  166 egoutPCB(sc, b)
  167         struct eg_softc *sc;
  168         u_char b;
  169 {
  170         bus_space_tag_t bst = sc->sc_bst;
  171         bus_space_handle_t bsh = sc->sc_bsh;
  172         int i;
  173 
  174         for (i = 0; i < 4000; i++) {
  175                 if (bus_space_read_1(bst, bsh, EG_STATUS) & EG_STAT_HCRE) {
  176                         bus_space_write_1(bst, bsh, EG_COMMAND, b);
  177                         return 0;
  178                 }
  179                 delay(10);
  180         }
  181         DPRINTF(("egoutPCB failed\n"));
  182         return (1);
  183 }
  184         
  185 static int
  186 egreadPCBstat(sc, statb)
  187         struct eg_softc *sc;
  188         u_char statb;
  189 {
  190         bus_space_tag_t bst = sc->sc_bst;
  191         bus_space_handle_t bsh = sc->sc_bsh;
  192         int i;
  193 
  194         for (i=0; i < 5000; i++) {
  195                 if ((bus_space_read_1(bst, bsh, EG_STATUS) & EG_PCB_STAT) !=
  196                     EG_PCB_NULL) 
  197                         break;
  198                 delay(10);
  199         }
  200         if ((bus_space_read_1(bst, bsh, EG_STATUS) & EG_PCB_STAT) == statb) 
  201                 return (0);
  202         return (1);
  203 }
  204 
  205 static int
  206 egreadPCBready(sc)
  207         struct eg_softc *sc;
  208 {
  209         bus_space_tag_t bst = sc->sc_bst;
  210         bus_space_handle_t bsh = sc->sc_bsh;
  211         int i;
  212 
  213         for (i=0; i < 10000; i++) {
  214                 if (bus_space_read_1(bst, bsh, EG_STATUS) & EG_STAT_ACRF)
  215                         return (0);
  216                 delay(5);
  217         }
  218         DPRINTF(("PCB read not ready status %02x\n",
  219             bus_space_read_1(bst, bsh, EG_STATUS)));
  220         return (1);
  221 }
  222         
  223 static int
  224 egwritePCB(sc)
  225         struct eg_softc *sc;
  226 {
  227         bus_space_tag_t bst = sc->sc_bst;
  228         bus_space_handle_t bsh = sc->sc_bsh;
  229         int i;
  230         u_char len;
  231 
  232         bus_space_write_1(bst, bsh, EG_CONTROL,
  233             (bus_space_read_1(bst, bsh, EG_CONTROL) & ~EG_PCB_STAT) |
  234             EG_PCB_NULL);
  235 
  236         len = sc->eg_pcb[1] + 2;
  237         for (i = 0; i < len; i++)
  238                 egoutPCB(sc, sc->eg_pcb[i]);
  239         
  240         for (i=0; i < 4000; i++) {
  241                 if (bus_space_read_1(bst, bsh, EG_STATUS) & EG_STAT_HCRE)
  242                         break;
  243                 delay(10);
  244         }
  245 
  246         bus_space_write_1(bst, bsh, EG_CONTROL,
  247             (bus_space_read_1(bst, bsh, EG_CONTROL) & ~EG_PCB_STAT) |
  248             EG_PCB_DONE);
  249 
  250         egoutPCB(sc, len);
  251 
  252         if (egreadPCBstat(sc, EG_PCB_ACCEPT))
  253                 return (1);
  254         return (0);
  255 }       
  256         
  257 static int
  258 egreadPCB(sc)
  259         struct eg_softc *sc;
  260 {
  261         bus_space_tag_t bst = sc->sc_bst;
  262         bus_space_handle_t bsh = sc->sc_bsh;
  263         int i;
  264         u_char b;
  265         
  266         bus_space_write_1(bst, bsh, EG_CONTROL,
  267             (bus_space_read_1(bst, bsh, EG_CONTROL) & ~EG_PCB_STAT) |
  268             EG_PCB_NULL);
  269 
  270         bzero(sc->eg_pcb, sizeof(sc->eg_pcb));
  271 
  272         if (egreadPCBready(sc))
  273                 return (1);
  274 
  275         sc->eg_pcb[0] = bus_space_read_1(bst, bsh, EG_COMMAND);
  276         
  277         if (egreadPCBready(sc))
  278                 return (1);
  279 
  280         sc->eg_pcb[1] = bus_space_read_1(bst, bsh, EG_COMMAND);
  281 
  282         if (sc->eg_pcb[1] > 62) {
  283                 DPRINTF(("len %d too large\n", sc->eg_pcb[1]));
  284                 return (1);
  285         }
  286         
  287         for (i = 0; i < sc->eg_pcb[1]; i++) {
  288                 if (egreadPCBready(sc))
  289                         return (1);
  290                 sc->eg_pcb[2+i] = bus_space_read_1(bst, bsh, EG_COMMAND);
  291         }
  292         if (egreadPCBready(sc))
  293                 return (1);
  294         if (egreadPCBstat(sc, EG_PCB_DONE))
  295                 return (1);
  296         if ((b = bus_space_read_1(bst, bsh, EG_COMMAND)) != sc->eg_pcb[1] + 2) {
  297                 DPRINTF(("%d != %d\n", b, sc->eg_pcb[1] + 2));
  298                 return (1);
  299         }
  300 
  301         bus_space_write_1(bst, bsh, EG_CONTROL,
  302             (bus_space_read_1(bst, bsh, EG_CONTROL) & ~EG_PCB_STAT) |
  303             EG_PCB_ACCEPT);
  304 
  305         return (0);
  306 }       
  307 
  308 /*
  309  * Real stuff
  310  */
  311 
  312 int
  313 egprobe(parent, match, aux)
  314         struct device *parent;
  315         void *match, *aux;
  316 {
  317         struct eg_softc *sc = match;
  318         struct isa_attach_args *ia = aux;
  319         bus_space_tag_t bst = sc->sc_bst = ia->ia_iot;
  320         bus_space_handle_t bsh;
  321         int i;
  322 
  323         if ((ia->ia_iobase & ~0x07f0) != 0) {
  324                 DPRINTF(("Weird iobase %x\n", ia->ia_iobase));
  325                 return (0);
  326         }
  327         
  328         if (bus_space_map(bst, ia->ia_iobase, EG_IO_PORTS, 0, &bsh)) {
  329                 DPRINTF(("%s: can't map I/O space\n", sc->sc_dev.dv_xname));
  330                 return (0);
  331         }
  332         sc->sc_bsh = bsh;
  333 
  334         /* hard reset card */
  335         bus_space_write_1(bst, bsh, EG_CONTROL, EG_CTL_RESET); 
  336         bus_space_write_1(bst, bsh, EG_CONTROL, 0);
  337         for (i = 0; i < 5000; i++) {
  338                 delay(1000);
  339                 if ((bus_space_read_1(bst, bsh, EG_STATUS) & EG_PCB_STAT) ==
  340                     EG_PCB_NULL) 
  341                         break;
  342         }
  343         if ((bus_space_read_1(bst, bsh, EG_STATUS) & EG_PCB_STAT) !=
  344             EG_PCB_NULL) {
  345                 DPRINTF(("eg: Reset failed\n"));
  346                 goto lose;
  347         }
  348         sc->eg_pcb[0] = EG_CMD_GETINFO; /* Get Adapter Info */
  349         sc->eg_pcb[1] = 0;
  350         if (egwritePCB(sc) != 0)
  351                 goto lose;
  352         
  353         if (egreadPCB(sc) != 0) {
  354                 egprintpcb(sc);
  355                 goto lose;
  356         }
  357 
  358         if (sc->eg_pcb[0] != EG_RSP_GETINFO || /* Get Adapter Info Response */
  359             sc->eg_pcb[1] != 0x0a) {
  360                 egprintpcb(sc);
  361                 goto lose;
  362         }
  363         sc->eg_rom_major = sc->eg_pcb[3];
  364         sc->eg_rom_minor = sc->eg_pcb[2];
  365         sc->eg_ram = sc->eg_pcb[6] | (sc->eg_pcb[7] << 8);
  366         
  367         ia->ia_iosize = 0x08;
  368         ia->ia_msize = 0;
  369         bus_space_unmap(bst, bsh, EG_IO_PORTS);
  370         return (1);
  371 
  372 lose:
  373         bus_space_unmap(bst, bsh, EG_IO_PORTS);
  374         return (0);
  375 }
  376 
  377 void
  378 egattach(parent, self, aux)
  379         struct device *parent, *self;
  380         void *aux;
  381 {
  382         struct eg_softc *sc = (void *)self;
  383         struct isa_attach_args *ia = aux;
  384         bus_space_tag_t bst = sc->sc_bst = ia->ia_iot;
  385         bus_space_handle_t bsh;
  386         struct ifnet *ifp = &sc->sc_arpcom.ac_if;
  387         
  388         if (bus_space_map(bst, ia->ia_iobase, EG_IO_PORTS, 0, &bsh)) {
  389                 printf("%s: can't map i/o space\n", sc->sc_dev.dv_xname);
  390                 return;
  391         }
  392         sc->sc_bsh = bsh;
  393 
  394         egstop(sc);
  395 
  396         sc->eg_pcb[0] = EG_CMD_GETEADDR; /* Get Station address */
  397         sc->eg_pcb[1] = 0;
  398         if (egwritePCB(sc) != 0) {
  399                 DPRINTF(("write error\n"));
  400                 return;
  401         }       
  402         if (egreadPCB(sc) != 0) {
  403                 DPRINTF(("read error\n"));
  404                 egprintpcb(sc);
  405                 return;
  406         }
  407 
  408         /* check Get station address response */
  409         if (sc->eg_pcb[0] != EG_RSP_GETEADDR || sc->eg_pcb[1] != 0x06) { 
  410                 DPRINTF(("parse error\n"));
  411                 egprintpcb(sc);
  412                 return;
  413         }
  414         bcopy(&sc->eg_pcb[2], sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN);
  415 
  416         printf(": ROM v%d.%02d %dk address %s\n",
  417             sc->eg_rom_major, sc->eg_rom_minor, sc->eg_ram,
  418             ether_sprintf(sc->sc_arpcom.ac_enaddr));
  419 
  420         sc->eg_pcb[0] = EG_CMD_SETEADDR; /* Set station address */
  421         if (egwritePCB(sc) != 0) {
  422                 DPRINTF(("write error2\n"));
  423                 return;
  424         }
  425         if (egreadPCB(sc) != 0) {
  426                 DPRINTF(("read error2\n"));
  427                 egprintpcb(sc);
  428                 return;
  429         }
  430         if (sc->eg_pcb[0] != EG_RSP_SETEADDR || sc->eg_pcb[1] != 0x02 ||
  431             sc->eg_pcb[2] != 0 || sc->eg_pcb[3] != 0) {
  432                 DPRINTF(("parse error2\n"));
  433                 egprintpcb(sc);
  434                 return;
  435         }
  436 
  437         /* Initialize ifnet structure. */
  438         bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
  439         ifp->if_softc = sc;
  440         ifp->if_start = egstart;
  441         ifp->if_ioctl = egioctl;
  442         ifp->if_watchdog = egwatchdog;
  443         ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS;
  444         IFQ_SET_READY(&ifp->if_snd);
  445         
  446         /* Now we can attach the interface. */
  447         if_attach(ifp);
  448         ether_ifattach(ifp);
  449         
  450         sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
  451             IPL_NET, egintr, sc, sc->sc_dev.dv_xname);
  452 }
  453 
  454 void
  455 eginit(sc)
  456         register struct eg_softc *sc;
  457 {
  458         bus_space_tag_t bst = sc->sc_bst;
  459         bus_space_handle_t bsh = sc->sc_bsh;
  460         register struct ifnet *ifp = &sc->sc_arpcom.ac_if;
  461 
  462         /* soft reset the board */
  463         bus_space_write_1(bst, bsh, EG_CONTROL, EG_CTL_FLSH);
  464         delay(100);
  465         bus_space_write_1(bst, bsh, EG_CONTROL, EG_CTL_ATTN);
  466         delay(100);
  467         bus_space_write_1(bst, bsh, EG_CONTROL, 0);
  468         delay(200);
  469 
  470         sc->eg_pcb[0] = EG_CMD_CONFIG82586; /* Configure 82586 */
  471         sc->eg_pcb[1] = 2;
  472         sc->eg_pcb[2] = 3; /* receive broadcast & multicast */
  473         sc->eg_pcb[3] = 0;
  474         if (egwritePCB(sc) != 0)
  475                 DPRINTF(("write error3\n"));
  476 
  477         if (egreadPCB(sc) != 0) {
  478                 DPRINTF(("read error3\n"));
  479                 egprintpcb(sc);
  480         } else if (sc->eg_pcb[2] != 0 || sc->eg_pcb[3] != 0)
  481                 printf("%s: configure card command failed\n",
  482                     sc->sc_dev.dv_xname);
  483 
  484         if (sc->eg_inbuf == 0)
  485                 sc->eg_inbuf = malloc(EG_BUFLEN, M_TEMP, M_NOWAIT);
  486         sc->eg_incount = 0;
  487 
  488         if (sc->eg_outbuf == 0)
  489                 sc->eg_outbuf = malloc(EG_BUFLEN, M_TEMP, M_NOWAIT);
  490 
  491         bus_space_write_1(bst, bsh, EG_CONTROL, EG_CTL_CMDE);
  492 
  493         sc->eg_incount = 0;
  494         egrecv(sc);
  495 
  496         /* Interface is now `running', with no output active. */
  497         ifp->if_flags |= IFF_RUNNING;
  498         ifp->if_flags &= ~IFF_OACTIVE;
  499 
  500         /* Attempt to start output, if any. */
  501         egstart(ifp);
  502 }
  503 
  504 void
  505 egrecv(sc)
  506         struct eg_softc *sc;
  507 {
  508 
  509         while (sc->eg_incount < EG_INLEN) {
  510                 sc->eg_pcb[0] = EG_CMD_RECVPACKET;
  511                 sc->eg_pcb[1] = 0x08;
  512                 sc->eg_pcb[2] = 0; /* address not used.. we send zero */
  513                 sc->eg_pcb[3] = 0;
  514                 sc->eg_pcb[4] = 0;
  515                 sc->eg_pcb[5] = 0;
  516                 sc->eg_pcb[6] = EG_BUFLEN & 0xff; /* our buffer size */
  517                 sc->eg_pcb[7] = (EG_BUFLEN >> 8) & 0xff;
  518                 sc->eg_pcb[8] = 0; /* timeout, 0 == none */
  519                 sc->eg_pcb[9] = 0;
  520                 if (egwritePCB(sc) != 0)
  521                         break;
  522                 sc->eg_incount++;
  523         }
  524 }
  525 
  526 void
  527 egstart(ifp)
  528         struct ifnet *ifp;
  529 {
  530         struct eg_softc *sc = ifp->if_softc;
  531         bus_space_tag_t bst = sc->sc_bst;
  532         bus_space_handle_t bsh = sc->sc_bsh;
  533         struct mbuf *m0, *m;
  534         caddr_t buffer;
  535         int len;
  536         u_short *ptr;
  537         u_int i;
  538 
  539         /* Don't transmit if interface is busy or not running */
  540         if ((ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING)
  541                 return;
  542 
  543 loop:
  544         /* Dequeue the next datagram. */
  545         IFQ_DEQUEUE(&ifp->if_snd, m0);
  546         if (m0 == 0)
  547                 return;
  548         
  549         ifp->if_flags |= IFF_OACTIVE;
  550 
  551         /* We need to use m->m_pkthdr.len, so require the header */
  552         if ((m0->m_flags & M_PKTHDR) == 0)
  553                 panic("egstart: no header mbuf");
  554         len = max(m0->m_pkthdr.len, ETHER_MIN_LEN);
  555 
  556 #if NBPFILTER > 0
  557         if (ifp->if_bpf)
  558                 bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT);
  559 #endif
  560 
  561         sc->eg_pcb[0] = EG_CMD_SENDPACKET;
  562         sc->eg_pcb[1] = 0x06;
  563         sc->eg_pcb[2] = 0; /* address not used, we send zero */
  564         sc->eg_pcb[3] = 0;
  565         sc->eg_pcb[4] = 0;
  566         sc->eg_pcb[5] = 0;
  567         sc->eg_pcb[6] = len; /* length of packet */
  568         sc->eg_pcb[7] = len >> 8;
  569         if (egwritePCB(sc) != 0) {
  570                 DPRINTF(("egwritePCB in egstart failed\n"));
  571                 ifp->if_oerrors++;
  572                 ifp->if_flags &= ~IFF_OACTIVE;
  573                 m_freem(m0);
  574                 goto loop;
  575         }
  576 
  577         buffer = sc->eg_outbuf;
  578         for (m = m0; m != 0; m = m->m_next) {
  579                 bcopy(mtod(m, caddr_t), buffer, m->m_len);
  580                 buffer += m->m_len;
  581         }
  582         if (len > m0->m_pkthdr.len)
  583                 bzero(buffer, len - m0->m_pkthdr.len);
  584 
  585         /* set direction bit: host -> adapter */
  586         bus_space_write_1(bst, bsh, EG_CONTROL,
  587             bus_space_read_1(bst, bsh, EG_CONTROL) & ~EG_CTL_DIR); 
  588         
  589         for (ptr = (u_short *)sc->eg_outbuf; len > 0; len -= 2) {
  590                 bus_space_write_2(bst, bsh, EG_DATA, *ptr++);
  591                 for (i = 10000; i != 0; i--) {
  592                         if (bus_space_read_1(bst, bsh, EG_STATUS) & EG_STAT_HRDY)
  593                                 break;
  594                         delay(10);
  595                 }
  596                 if (i == 0) {
  597                         printf("%s: start failed\n", sc->sc_dev.dv_xname);
  598                         break;
  599                 }
  600         }
  601         
  602         m_freem(m0);
  603 }
  604 
  605 int
  606 egintr(arg)
  607         void *arg;
  608 {
  609         struct eg_softc *sc = arg;
  610         bus_space_tag_t bst = sc->sc_bst;
  611         bus_space_handle_t bsh = sc->sc_bsh;
  612         int ret = 0;
  613         int i, len;
  614         u_short *ptr;
  615 
  616         while (bus_space_read_1(bst, bsh, EG_STATUS) & EG_STAT_ACRF) {
  617                 ret = 1;
  618                 egreadPCB(sc);
  619                 switch (sc->eg_pcb[0]) {
  620                 case EG_RSP_RECVPACKET:
  621                         len = sc->eg_pcb[6] | (sc->eg_pcb[7] << 8);
  622         
  623                         /* Set direction bit : Adapter -> host */
  624                         bus_space_write_1(bst, bsh, EG_CONTROL,
  625                             bus_space_read_1(bst, bsh, EG_CONTROL) |
  626                             EG_CTL_DIR); 
  627 
  628                         for (ptr = (u_short *)sc->eg_inbuf; len > 0; len -= 2) {
  629                                 for (i = 10000; i != 0; i--) {
  630                                         if (bus_space_read_1(bst, bsh, EG_STATUS) & EG_STAT_HRDY)
  631                                                 break;
  632                                         delay(10);
  633                                 }
  634                                 if (i == 0) {
  635                                         printf("%s: receive failed\n",
  636                                             sc->sc_dev.dv_xname);
  637                                         break;
  638                                 }
  639                                 *ptr++ = bus_space_read_2(bst, bsh, EG_DATA);
  640                         }
  641 
  642                         if (len <= 0) {
  643                                 len = sc->eg_pcb[8] | (sc->eg_pcb[9] << 8);
  644                                 egread(sc, sc->eg_inbuf, len);
  645 
  646                                 sc->eg_incount--;
  647                                 egrecv(sc);
  648                         }
  649                         break;
  650 
  651                 case EG_RSP_SENDPACKET:
  652                         if (sc->eg_pcb[6] || sc->eg_pcb[7]) {
  653                                 DPRINTF(("packet dropped\n"));
  654                                 sc->sc_arpcom.ac_if.if_oerrors++;
  655                         } else
  656                                 sc->sc_arpcom.ac_if.if_opackets++;
  657                         sc->sc_arpcom.ac_if.if_collisions +=
  658                             sc->eg_pcb[8] & 0xf;
  659                         sc->sc_arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
  660                         egstart(&sc->sc_arpcom.ac_if);
  661                         break;
  662 
  663                 case EG_RSP_GETSTATS:
  664                         DPRINTF(("Card Statistics\n"));
  665                         bcopy(&sc->eg_pcb[2], &i, sizeof(i));
  666                         DPRINTF(("Receive Packets %d\n", i));
  667                         bcopy(&sc->eg_pcb[6], &i, sizeof(i));
  668                         DPRINTF(("Transmit Packets %d\n", i));
  669                         DPRINTF(("CRC errors %d\n", *(short *)&sc->eg_pcb[10]));
  670                         DPRINTF(("alignment errors %d\n",
  671                             *(short *)&sc->eg_pcb[12]));
  672                         DPRINTF(("no resources errors %d\n",
  673                             *(short *)&sc->eg_pcb[14]));
  674                         DPRINTF(("overrun errors %d\n",
  675                             *(short *)&sc->eg_pcb[16]));
  676                         break;
  677                         
  678                 default:
  679                         DPRINTF(("egintr: Unknown response %x??\n",
  680                             sc->eg_pcb[0]));
  681                         egprintpcb(sc);
  682                         break;
  683                 }
  684         }
  685 
  686         return (ret);
  687 }
  688 
  689 /*
  690  * Pass a packet up to the higher levels.
  691  */
  692 void
  693 egread(sc, buf, len)
  694         struct eg_softc *sc;
  695         caddr_t buf;
  696         int len;
  697 {
  698         struct ifnet *ifp = &sc->sc_arpcom.ac_if;
  699         struct mbuf *m;
  700         
  701         if (len <= sizeof(struct ether_header) ||
  702             len > ETHER_MAX_LEN) {
  703                 printf("%s: invalid packet size %d; dropping\n",
  704                     sc->sc_dev.dv_xname, len);
  705                 ifp->if_ierrors++;
  706                 return;
  707         }
  708 
  709         /* Pull packet off interface. */
  710         m = egget(sc, buf, len);
  711         if (m == 0) {
  712                 ifp->if_ierrors++;
  713                 return;
  714         }
  715 
  716         ifp->if_ipackets++;
  717 
  718 #if NBPFILTER > 0
  719         /*
  720          * Check if there's a BPF listener on this interface.
  721          * If so, hand off the raw packet to BPF.
  722          */
  723         if (ifp->if_bpf)
  724                 bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
  725 #endif
  726 
  727         ether_input_mbuf(ifp, m);
  728 }
  729 
  730 /*
  731  * convert buf into mbufs
  732  */
  733 struct mbuf *
  734 egget(sc, buf, totlen)
  735         struct eg_softc *sc;
  736         caddr_t buf;
  737         int totlen;
  738 {
  739         struct ifnet *ifp = &sc->sc_arpcom.ac_if;
  740         struct mbuf *top, **mp, *m;
  741         int len;
  742 
  743         MGETHDR(m, M_DONTWAIT, MT_DATA);
  744         if (m == 0)
  745                 return (0);
  746         m->m_pkthdr.rcvif = ifp;
  747         m->m_pkthdr.len = totlen;
  748         len = MHLEN;
  749         top = 0;
  750         mp = &top;
  751 
  752         while (totlen > 0) {
  753                 if (top) {
  754                         MGET(m, M_DONTWAIT, MT_DATA);
  755                         if (m == 0) {
  756                                 m_freem(top);
  757                                 return (0);
  758                         }
  759                         len = MLEN;
  760                 }
  761                 if (totlen >= MINCLSIZE) {
  762                         MCLGET(m, M_DONTWAIT);
  763                         if (m->m_flags & M_EXT)
  764                                 len = MCLBYTES;
  765                 }
  766                 m->m_len = len = min(totlen, len);
  767                 bcopy((caddr_t)buf, mtod(m, caddr_t), len);
  768                 buf += len;
  769                 totlen -= len;
  770                 *mp = m;
  771                 mp = &m->m_next;
  772         }
  773 
  774         return (top);
  775 }
  776 
  777 int
  778 egioctl(ifp, cmd, data)
  779         register struct ifnet *ifp;
  780         u_long cmd;
  781         caddr_t data;
  782 {
  783         struct eg_softc *sc = ifp->if_softc;
  784         struct ifaddr *ifa = (struct ifaddr *)data;
  785         int s, error = 0;
  786 
  787         s = splnet();
  788 
  789         if ((error = ether_ioctl(ifp, &sc->sc_arpcom, cmd, data)) > 0) {
  790                 splx(s);
  791                 return (error);
  792         }
  793 
  794         switch (cmd) {
  795 
  796         case SIOCSIFADDR:
  797                 ifp->if_flags |= IFF_UP;
  798 
  799                 switch (ifa->ifa_addr->sa_family) {
  800 #ifdef INET
  801                 case AF_INET:
  802                         eginit(sc);
  803                         arp_ifinit(&sc->sc_arpcom, ifa);
  804                         break;
  805 #endif
  806                 default:
  807                         eginit(sc);
  808                         break;
  809                 }
  810                 break;
  811 
  812         case SIOCSIFFLAGS:
  813                 if ((ifp->if_flags & IFF_UP) == 0 &&
  814                     (ifp->if_flags & IFF_RUNNING) != 0) {
  815                         /*
  816                          * If interface is marked down and it is running, then
  817                          * stop it.
  818                          */
  819                         egstop(sc);
  820                         ifp->if_flags &= ~IFF_RUNNING;
  821                 } else if ((ifp->if_flags & IFF_UP) != 0 &&
  822                            (ifp->if_flags & IFF_RUNNING) == 0) {
  823                         /*
  824                          * If interface is marked up and it is stopped, then
  825                          * start it.
  826                          */
  827                         eginit(sc);
  828                 } else {
  829                         sc->eg_pcb[0] = EG_CMD_GETSTATS;
  830                         sc->eg_pcb[1] = 0;
  831                         if (egwritePCB(sc) != 0)
  832                                 DPRINTF(("write error\n"));
  833                         /*
  834                          * XXX deal with flags changes:
  835                          * IFF_MULTICAST, IFF_PROMISC,
  836                          * IFF_LINK0, IFF_LINK1,
  837                          */
  838                 }
  839                 break;
  840 
  841         default:
  842                 error = EINVAL;
  843                 break;
  844         }
  845 
  846         splx(s);
  847         return (error);
  848 }
  849 
  850 void
  851 egreset(sc)
  852         struct eg_softc *sc;
  853 {
  854         int s;
  855 
  856         DPRINTF(("egreset()\n"));
  857         s = splnet();
  858         egstop(sc);
  859         eginit(sc);
  860         splx(s);
  861 }
  862 
  863 void
  864 egwatchdog(ifp)
  865         struct ifnet *ifp;
  866 {
  867         struct eg_softc *sc = ifp->if_softc;
  868 
  869         log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
  870         sc->sc_arpcom.ac_if.if_oerrors++;
  871 
  872         egreset(sc);
  873 }
  874 
  875 void
  876 egstop(sc)
  877         register struct eg_softc *sc;
  878 {
  879         bus_space_tag_t bst = sc->sc_bst;
  880         bus_space_handle_t bsh = sc->sc_bsh;
  881         
  882         bus_space_write_1(bst, bsh, EG_CONTROL, 0);
  883 }

/* [<][>][^][v][top][bottom][index][help] */