The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/isa/if_ex.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $OpenBSD: if_ex.c,v 1.48 2022/04/06 18:59:28 naddy Exp $        */
    2 /*
    3  * Copyright (c) 1997, Donald A. Schmidt
    4  * Copyright (c) 1996, Javier Martín Rueda (jmrueda@diatel.upm.es)
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice unmodified, this list of conditions, and the following
   12  *    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  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   27  * SUCH DAMAGE.
   28  */
   29 
   30 /*
   31  * Intel EtherExpress Pro/10 Ethernet driver
   32  *
   33  * Revision history:
   34  *
   35  * 30-Oct-1996: first beta version. Inet and BPF supported, but no multicast.
   36  */
   37 
   38 #include "bpfilter.h"
   39 
   40 #include <sys/param.h>
   41 #include <sys/systm.h>
   42 #include <sys/conf.h>
   43 #include <sys/sockio.h>
   44 #include <sys/mbuf.h>
   45 #include <sys/socket.h>
   46 #include <sys/device.h>
   47 
   48 #include <net/if.h>
   49 #include <net/if_media.h> 
   50 
   51 #include <netinet/in.h>
   52 #include <netinet/if_ether.h>
   53 
   54 #if NBPFILTER > 0
   55 #include <net/bpf.h>
   56 #endif
   57 
   58 #include <machine/cpu.h>
   59 #include <machine/bus.h>
   60 
   61 #include <dev/isa/isavar.h>
   62 #include <dev/isa/if_exreg.h>
   63 
   64 #ifdef EX_DEBUG
   65 #define Start_End 1
   66 #define Rcvd_Pkts 2
   67 #define Sent_Pkts 4
   68 #define Status    8
   69 static int debug_mask = 0;
   70 static int exintr_count = 0;
   71 #define DODEBUG(level, action) if (level & debug_mask) action
   72 #else
   73 #define DODEBUG(level, action)
   74 #endif
   75 
   76 struct ex_softc {
   77         struct arpcom arpcom;   /* Ethernet common data */
   78         struct ifmedia ifmedia;
   79         int iobase;             /* I/O base address. */
   80         u_short irq_no;         /* IRQ number. */
   81         u_int mem_size;         /* Total memory size, in bytes. */
   82         u_int rx_mem_size;      /* Rx memory size (by default, first 3/4 of 
   83                                    total memory). */
   84         u_int rx_lower_limit, 
   85               rx_upper_limit;   /* Lower and upper limits of receive buffer. */
   86         u_int rx_head;          /* Head of receive ring buffer. */
   87         u_int tx_mem_size;      /* Tx memory size (by default, last quarter of 
   88                                    total memory). */
   89         u_int tx_lower_limit, 
   90               tx_upper_limit;   /* Lower and upper limits of transmit buffer. */
   91         u_int tx_head, tx_tail; /* Head and tail of transmit ring buffer. */
   92         u_int tx_last;          /* Pointer to beginning of last frame in the 
   93                                    chain. */
   94         bus_space_tag_t sc_iot; /* ISA i/o space tag */
   95         bus_space_handle_t sc_ioh; /* ISA i/o space handle */
   96         void *sc_ih;            /* Device interrupt handler */
   97 };
   98 
   99 static char irq2eemap[] = { -1, -1, 0, 1, -1, 2, -1, -1, -1, 0, 3, 4, -1, -1, 
  100                             -1, -1 };
  101 static u_char ee2irqmap[] = { 9, 3, 5, 10, 11, 0, 0, 0 };
  102 
  103 int ex_probe(struct device *, void *, void *);
  104 void ex_attach(struct device *, struct device *, void *);
  105 void ex_init(struct ex_softc *);
  106 void ex_start(struct ifnet *);
  107 void ex_stop(struct ex_softc *);
  108 int ex_ioctl(struct ifnet *, u_long, caddr_t);
  109 void ex_setmulti(struct ex_softc *);
  110 void ex_reset(struct ex_softc *);
  111 void ex_watchdog(struct ifnet *);
  112 uint64_t ex_get_media(struct ex_softc *);
  113 
  114 int ex_ifmedia_upd(struct ifnet *);
  115 void ex_ifmedia_sts(struct ifnet *, struct ifmediareq *);
  116 
  117 u_short ex_eeprom_read(struct ex_softc *, int);
  118 int ex_look_for_card(struct isa_attach_args *, struct ex_softc *sc);
  119 
  120 int ex_intr(void *);
  121 void ex_tx_intr(struct ex_softc *);
  122 void ex_rx_intr(struct ex_softc *);
  123 
  124 const struct cfattach ex_ca = {
  125         sizeof(struct ex_softc), ex_probe, ex_attach
  126 };
  127 
  128 struct cfdriver ex_cd = {
  129         NULL, "ex", DV_IFNET
  130 };
  131 
  132 #define CSR_READ_1(sc, off) \
  133         bus_space_read_1((sc)->sc_iot, (sc)->sc_ioh, (off))
  134 #define CSR_READ_2(sc, off) \
  135         bus_space_read_2((sc)->sc_iot, (sc)->sc_ioh, (off))
  136 #define CSR_READ_MULTI_2(sc, off, addr, count) \
  137         bus_space_read_multi_2((sc)->sc_iot, (sc)->sc_ioh, (off),       \
  138             (u_int16_t *)(addr), (count))
  139 
  140 #define CSR_WRITE_1(sc, off, value) \
  141         bus_space_write_1((sc)->sc_iot, (sc)->sc_ioh, (off), (value))
  142 #define CSR_WRITE_2(sc, off, value) \
  143         bus_space_write_2((sc)->sc_iot, (sc)->sc_ioh, (off), (value))
  144 #define CSR_WRITE_MULTI_2(sc, off, addr, count) \
  145         bus_space_write_multi_2((sc)->sc_iot, (sc)->sc_ioh, (off),      \
  146             (u_int16_t *)(addr), (count))
  147 
  148 int 
  149 ex_look_for_card(struct isa_attach_args *ia, struct ex_softc *sc)
  150 {
  151         int count1, count2;
  152 
  153         /*
  154          * Check for the i82595 signature, and check that the round robin
  155          * counter actually advances.
  156          */
  157         if (((count1 = CSR_READ_1(sc, ID_REG)) & Id_Mask) != Id_Sig)
  158                 return(0);
  159         count2 = CSR_READ_1(sc, ID_REG);
  160         count2 = CSR_READ_1(sc, ID_REG);
  161         count2 = CSR_READ_1(sc, ID_REG);
  162         if ((count2 & Counter_bits) == ((count1 + 0xc0) & Counter_bits))
  163                 return(1);
  164         else
  165                 return(0);
  166 }
  167 
  168 int 
  169 ex_probe(struct device *parent, void *match, void *aux)
  170 {
  171         struct ex_softc *sc = match;
  172         struct isa_attach_args *ia = aux;
  173         u_short eaddr_tmp;
  174         int tmp;
  175 
  176         DODEBUG(Start_End, printf("ex_probe: start\n"););
  177 
  178         if ((ia->ia_iobase >= 0x200) && (ia->ia_iobase <= 0x3a0)) {
  179                 sc->sc_iot = ia->ia_iot;
  180                 if(bus_space_map(sc->sc_iot, ia->ia_iobase, EX_IOSIZE, 0,
  181                     &sc->sc_ioh))
  182                         return(0);
  183 
  184                 if (!ex_look_for_card(ia, sc)) {
  185                         bus_space_unmap(sc->sc_iot, sc->sc_ioh, EX_IOSIZE);
  186                         return(0); 
  187                 }
  188         } else
  189                 return(0);
  190 
  191         ia->ia_iosize = EX_IOSIZE;
  192 
  193         /*
  194          * Reset the card.
  195          */
  196         CSR_WRITE_1(sc, CMD_REG, Reset_CMD);
  197         delay(200);
  198 
  199         /*
  200          * Fill in several fields of the softc structure:
  201          *      - I/O base address.
  202          *      - Hardware Ethernet address.
  203          *      - IRQ number (if not supplied in config file, read it from 
  204          *        EEPROM).
  205          */
  206         sc->iobase = ia->ia_iobase;
  207         eaddr_tmp = ex_eeprom_read(sc, EE_Eth_Addr_Lo);
  208         sc->arpcom.ac_enaddr[5] = eaddr_tmp & 0xff;
  209         sc->arpcom.ac_enaddr[4] = eaddr_tmp >> 8;
  210         eaddr_tmp = ex_eeprom_read(sc, EE_Eth_Addr_Mid);
  211         sc->arpcom.ac_enaddr[3] = eaddr_tmp & 0xff;
  212         sc->arpcom.ac_enaddr[2] = eaddr_tmp >> 8;
  213         eaddr_tmp = ex_eeprom_read(sc, EE_Eth_Addr_Hi);
  214         sc->arpcom.ac_enaddr[1] = eaddr_tmp & 0xff;
  215         sc->arpcom.ac_enaddr[0] = eaddr_tmp >> 8;
  216         tmp = ex_eeprom_read(sc, EE_IRQ_No) & IRQ_No_Mask;
  217         if (ia->ia_irq > 0) {
  218                 if (ee2irqmap[tmp] != ia->ia_irq)
  219                         printf("ex: WARING: board's EEPROM is configured for IRQ %d, using %d\n", ee2irqmap[tmp], ia->ia_irq);
  220                 sc->irq_no = ia->ia_irq;
  221         }
  222         else {
  223                 sc->irq_no = ee2irqmap[tmp];
  224                 ia->ia_irq = sc->irq_no;
  225         }
  226         if (sc->irq_no == 0) {
  227                 printf("ex: invalid IRQ.\n");
  228                 return(0);
  229         }
  230 
  231         sc->mem_size = CARD_RAM_SIZE;   /* XXX This should be read from the card
  232                                                itself. */
  233 
  234         DODEBUG(Start_End, printf("ex_probe: finish\n"););
  235         return(1);
  236 }
  237 
  238 void
  239 ex_attach(struct device *parent, struct device *self, void *aux)
  240 {
  241         struct ex_softc *sc = (void *)self;
  242         struct isa_attach_args *ia = aux;
  243         struct ifnet *ifp = &sc->arpcom.ac_if;
  244         struct ifmedia *ifm;
  245         int temp;
  246 
  247         DODEBUG(Start_End, printf("ex_attach: start\n"););
  248 
  249         ifp->if_softc = sc;
  250         bcopy(self->dv_xname, ifp->if_xname, IFNAMSIZ);
  251         ifp->if_start = ex_start;
  252         ifp->if_ioctl = ex_ioctl;
  253         ifp->if_watchdog = ex_watchdog;
  254         ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST;
  255 
  256         ifmedia_init(&sc->ifmedia, 0, ex_ifmedia_upd, ex_ifmedia_sts);
  257 
  258         temp = ex_eeprom_read(sc, EE_W5);
  259         if (temp & EE_W5_PORT_TPE)
  260                 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T, 0, NULL);
  261         if (temp & EE_W5_PORT_BNC)
  262                 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_2, 0, NULL);
  263         if (temp & EE_W5_PORT_AUI)
  264                 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_5, 0, NULL);
  265 
  266         ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_AUTO, 0, NULL);
  267         ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_NONE, 0, NULL);
  268         ifmedia_set(&sc->ifmedia, ex_get_media(sc));
  269 
  270         ifm = &sc->ifmedia;
  271         ifm->ifm_media = ifm->ifm_cur->ifm_media;
  272         ex_ifmedia_upd(ifp);
  273 
  274         if_attach(ifp);
  275         ether_ifattach(ifp);
  276         printf(": address %s\n",
  277             ether_sprintf(sc->arpcom.ac_enaddr));
  278 
  279         sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
  280             IPL_NET, ex_intr, sc, self->dv_xname);
  281         ex_init(sc);
  282 
  283         DODEBUG(Start_End, printf("ex_attach: finish\n"););
  284 }
  285 
  286 void 
  287 ex_init(struct ex_softc *sc)
  288 {
  289         struct ifnet *ifp = &sc->arpcom.ac_if;
  290         int s, i;
  291         unsigned short temp_reg;
  292 
  293         DODEBUG(Start_End, printf("ex_init: start\n"););
  294 
  295         s = splnet();
  296         sc->arpcom.ac_if.if_timer = 0;
  297 
  298         /*
  299          * Load the ethernet address into the card.
  300          */
  301         CSR_WRITE_1(sc, CMD_REG, Bank2_Sel);
  302         temp_reg = CSR_READ_1(sc, EEPROM_REG);
  303         if (temp_reg & Trnoff_Enable)
  304                 CSR_WRITE_1(sc, EEPROM_REG, temp_reg & ~Trnoff_Enable);
  305         for (i = 0; i < ETHER_ADDR_LEN; i++)
  306                 CSR_WRITE_1(sc, I_ADDR_REG0 + i, sc->arpcom.ac_enaddr[i]);
  307         /*
  308          * - Setup transmit chaining and discard bad received frames.
  309          * - Match broadcast.
  310          * - Clear test mode.
  311          * - Set receiving mode.
  312          * - Set IRQ number.
  313          */
  314         CSR_WRITE_1(sc, REG1, CSR_READ_1(sc, REG1) | Tx_Chn_Int_Md |
  315             Tx_Chn_ErStp | Disc_Bad_Fr);
  316         CSR_WRITE_1(sc, REG2, CSR_READ_1(sc, REG2) | No_SA_Ins |
  317             RX_CRC_InMem);
  318         CSR_WRITE_1(sc, REG3, (CSR_READ_1(sc, REG3) & 0x3f));
  319         CSR_WRITE_1(sc, CMD_REG, Bank1_Sel);
  320         CSR_WRITE_1(sc, INT_NO_REG, (CSR_READ_1(sc, INT_NO_REG) & 0xf8) | 
  321             irq2eemap[sc->irq_no]);
  322 
  323         /*
  324          * Divide the available memory in the card into rcv and xmt buffers.
  325          * By default, I use the first 3/4 of the memory for the rcv buffer,
  326          * and the remaining 1/4 of the memory for the xmt buffer.
  327          */
  328         sc->rx_mem_size = sc->mem_size * 3 / 4;
  329         sc->tx_mem_size = sc->mem_size - sc->rx_mem_size;
  330         sc->rx_lower_limit = 0x0000;
  331         sc->rx_upper_limit = sc->rx_mem_size - 2;
  332         sc->tx_lower_limit = sc->rx_mem_size;
  333         sc->tx_upper_limit = sc->mem_size - 2;
  334         CSR_WRITE_1(sc, RCV_LOWER_LIMIT_REG, sc->rx_lower_limit >> 8);
  335         CSR_WRITE_1(sc, RCV_UPPER_LIMIT_REG, sc->rx_upper_limit >> 8);
  336         CSR_WRITE_1(sc, XMT_LOWER_LIMIT_REG, sc->tx_lower_limit >> 8);
  337         CSR_WRITE_1(sc, XMT_UPPER_LIMIT_REG, sc->tx_upper_limit >> 8);
  338 
  339         /*
  340          * Enable receive and transmit interrupts, and clear any pending int.
  341          */
  342         CSR_WRITE_1(sc, REG1, CSR_READ_1(sc, REG1) | TriST_INT);
  343         CSR_WRITE_1(sc, CMD_REG, Bank0_Sel);
  344         CSR_WRITE_1(sc, MASK_REG, All_Int & ~(Rx_Int | Tx_Int));
  345         CSR_WRITE_1(sc, STATUS_REG, All_Int);
  346 
  347         /*
  348          * Initialize receive and transmit ring buffers.
  349          */
  350         CSR_WRITE_2(sc, RCV_BAR, sc->rx_lower_limit);
  351         sc->rx_head = sc->rx_lower_limit;
  352         CSR_WRITE_2(sc, RCV_STOP_REG, sc->rx_upper_limit | 0xfe);
  353         CSR_WRITE_2(sc, XMT_BAR, sc->tx_lower_limit);
  354         sc->tx_head = sc->tx_tail = sc->tx_lower_limit;
  355 
  356         ifp->if_flags |= IFF_RUNNING;
  357         ifq_clr_oactive(&ifp->if_snd);
  358         DODEBUG(Status, printf("OIDLE init\n"););
  359 
  360         ex_setmulti(sc);
  361 
  362         /*
  363          * Final reset of the board, and enable operation.
  364          */
  365         CSR_WRITE_1(sc, CMD_REG, Sel_Reset_CMD);
  366         delay(2);
  367         CSR_WRITE_1(sc, CMD_REG, Rcv_Enable_CMD);
  368 
  369         ex_start(ifp);
  370         splx(s);
  371 
  372         DODEBUG(Start_End, printf("ex_init: finish\n"););
  373 }
  374 
  375 void 
  376 ex_start(struct ifnet *ifp)
  377 {
  378         struct ex_softc *sc = ifp->if_softc;
  379         int i, len, data_len, avail, dest, next;
  380         unsigned char tmp16[2];
  381         struct mbuf *opkt;
  382         struct mbuf *m;
  383 
  384         DODEBUG(Start_End, printf("ex_start: start\n"););
  385 
  386         /*
  387          * Main loop: send outgoing packets to network card until there are no
  388          * more packets left, or the card cannot accept any more yet.
  389          */
  390         while (!ifq_is_oactive(&ifp->if_snd)) {
  391                 opkt = ifq_deq_begin(&ifp->if_snd);
  392                 if (opkt == NULL)
  393                         break;
  394 
  395                 /*
  396                  * Ensure there is enough free transmit buffer space for this 
  397                  * packet, including its header. Note: the header cannot wrap 
  398                  * around the end of the transmit buffer and must be kept 
  399                  * together, so we allow space for twice the length of the 
  400                  * header, just in case.
  401                  */
  402                 for (len = 0, m = opkt; m != NULL; m = m->m_next)
  403                         len += m->m_len;
  404                 data_len = len;
  405                 DODEBUG(Sent_Pkts, printf("1. Sending packet with %d data bytes. ", data_len););
  406                 if (len & 1)
  407                         len += XMT_HEADER_LEN + 1;
  408                 else
  409                         len += XMT_HEADER_LEN;
  410                 if ((i = sc->tx_tail - sc->tx_head) >= 0)
  411                         avail = sc->tx_mem_size - i;
  412                 else
  413                         avail = -i;
  414                 DODEBUG(Sent_Pkts, printf("i=%d, avail=%d\n", i, avail););
  415                 if (avail >= len + XMT_HEADER_LEN) {
  416                         ifq_deq_commit(&ifp->if_snd, opkt);
  417 
  418 #ifdef EX_PSA_INTR      
  419                         /*
  420                          * Disable rx and tx interrupts, to avoid corruption of
  421                          * the host address register by interrupt service 
  422                          * routines. XXX Is this necessary with splnet() 
  423                          * enabled?
  424                          */
  425                         CSR_WRITE_2(sc, MASK_REG, All_Int);
  426 #endif
  427 
  428                         /* 
  429                          * Compute the start and end addresses of this frame 
  430                          * in the tx buffer.
  431                          */
  432                         dest = sc->tx_tail;
  433                         next = dest + len;
  434                         if (next > sc->tx_upper_limit) {
  435                                 if ((sc->tx_upper_limit + 2 - sc->tx_tail) <= 
  436                                     XMT_HEADER_LEN) {
  437                                         dest = sc->tx_lower_limit;
  438                                         next = dest + len;
  439                                 } else
  440                                         next = sc->tx_lower_limit + next - 
  441                                             sc->tx_upper_limit - 2;
  442                         }
  443 
  444                         /* Build the packet frame in the card's ring buffer. */
  445                         DODEBUG(Sent_Pkts, printf("2. dest=%d, next=%d. ", dest, next););
  446                         CSR_WRITE_2(sc, HOST_ADDR_REG, dest);
  447                         CSR_WRITE_2(sc, IO_PORT_REG, Transmit_CMD);
  448                         CSR_WRITE_2(sc, IO_PORT_REG, 0);
  449                         CSR_WRITE_2(sc, IO_PORT_REG, next);
  450                         CSR_WRITE_2(sc, IO_PORT_REG, data_len);
  451 
  452                         /*
  453                          * Output the packet data to the card. Ensure all 
  454                          * transfers are 16-bit wide, even if individual mbufs 
  455                          * have odd length.
  456                          */
  457 
  458                         for (m = opkt, i = 0; m != NULL; m = m->m_next) {
  459                                 DODEBUG(Sent_Pkts, printf("[%d]", m->m_len););
  460                                 if (i) {
  461                                         tmp16[1] = *(mtod(m, caddr_t));
  462                                         CSR_WRITE_MULTI_2(sc, IO_PORT_REG, tmp16, 1);
  463                                 }
  464                                 CSR_WRITE_MULTI_2(sc, IO_PORT_REG, mtod(m, caddr_t) 
  465                                     + i, (m->m_len - i) / 2);
  466                                 if ((i = (m->m_len - i) & 1))
  467                                         tmp16[0] = *(mtod(m, caddr_t) + 
  468                                             m->m_len - 1);
  469                         }
  470                         if (i)
  471                                 CSR_WRITE_MULTI_2(sc, IO_PORT_REG, tmp16, 1);
  472 
  473                         /*
  474                          * If there were other frames chained, update the 
  475                          * chain in the last one.
  476                          */
  477                         if (sc->tx_head != sc->tx_tail) {
  478                                 if (sc->tx_tail != dest) {
  479                                         CSR_WRITE_2(sc, HOST_ADDR_REG, 
  480                                             sc->tx_last + XMT_Chain_Point);
  481                                         CSR_WRITE_2(sc, IO_PORT_REG, dest);
  482                                 }
  483                                 CSR_WRITE_2(sc, HOST_ADDR_REG, sc->tx_last + 
  484                                     XMT_Byte_Count);
  485                                 i = CSR_READ_2(sc, IO_PORT_REG);
  486                                 CSR_WRITE_2(sc, HOST_ADDR_REG, sc->tx_last + 
  487                                     XMT_Byte_Count);
  488                                 CSR_WRITE_2(sc, IO_PORT_REG, i | Ch_bit);
  489                         }
  490 
  491                         /*
  492                          * Resume normal operation of the card:
  493                          * -Make a dummy read to flush the DRAM write pipeline.
  494                          * -Enable receive and transmit interrupts.
  495                          * -Send Transmit or Resume_XMT command, as appropriate.
  496                          */
  497                         CSR_READ_2(sc, IO_PORT_REG);
  498 #ifdef EX_PSA_INTR
  499                         CSR_WRITE_2(sc, MASK_REG, All_Int & ~(Rx_Int | Tx_Int));
  500 #endif
  501                         if (sc->tx_head == sc->tx_tail) {
  502                                 CSR_WRITE_2(sc, XMT_BAR, dest);
  503                                 CSR_WRITE_1(sc, CMD_REG, Transmit_CMD);
  504                                 sc->tx_head = dest;
  505                                 DODEBUG(Sent_Pkts, printf("Transmit\n"););
  506                         } else {
  507                                 CSR_WRITE_1(sc, CMD_REG, Resume_XMT_List_CMD);
  508                                 DODEBUG(Sent_Pkts, printf("Resume\n"););
  509                         }
  510                         sc->tx_last = dest;
  511                         sc->tx_tail = next;
  512 #if NBPFILTER > 0
  513                         if (ifp->if_bpf != NULL)
  514                                 bpf_mtap(ifp->if_bpf, opkt,
  515                                     BPF_DIRECTION_OUT);
  516 #endif
  517                         ifp->if_timer = 2;
  518                         m_freem(opkt);
  519                 } else {
  520                         ifq_deq_rollback(&ifp->if_snd, opkt);
  521                         ifq_set_oactive(&ifp->if_snd);
  522                         DODEBUG(Status, printf("OACTIVE start\n"););
  523                 }
  524         }
  525 
  526         DODEBUG(Start_End, printf("ex_start: finish\n"););
  527 }
  528 
  529 void 
  530 ex_stop(struct ex_softc *sc)
  531 {
  532         DODEBUG(Start_End, printf("ex_stop: start\n"););
  533 
  534         /*
  535          * Disable card operation:
  536          * - Disable the interrupt line.
  537          * - Flush transmission and disable reception.
  538          * - Mask and clear all interrupts.
  539          * - Reset the 82595.
  540          */
  541         CSR_WRITE_1(sc, CMD_REG, Bank1_Sel);
  542         CSR_WRITE_1(sc, REG1, CSR_READ_1(sc, REG1) & ~TriST_INT);
  543         CSR_WRITE_1(sc, CMD_REG, Bank0_Sel);
  544         CSR_WRITE_1(sc, CMD_REG, Rcv_Stop);
  545         sc->tx_head = sc->tx_tail = sc->tx_lower_limit;
  546         sc->tx_last = 0; /* XXX I think these two lines are not necessary, 
  547                                 because ex_init will always be called again 
  548                                 to reinit the interface. */
  549         CSR_WRITE_1(sc, MASK_REG, All_Int);
  550         CSR_WRITE_1(sc, STATUS_REG, All_Int);
  551         CSR_WRITE_1(sc, CMD_REG, Reset_CMD);
  552         delay(200);
  553 
  554         DODEBUG(Start_End, printf("ex_stop: finish\n"););
  555 }
  556 
  557 
  558 int 
  559 ex_intr(void *arg)
  560 {
  561         struct ex_softc *sc = arg;
  562         struct ifnet *ifp = &sc->arpcom.ac_if;
  563         int int_status, send_pkts;
  564         int handled = 0;
  565 
  566         DODEBUG(Start_End, printf("exintr: start\n"););
  567 
  568 #ifdef EX_DEBUG
  569         if (++exintr_count != 1)
  570                 printf("WARNING: nested interrupt (%d). Mail the author.\n", 
  571                     exintr_count);
  572 #endif
  573 
  574         send_pkts = 0;
  575         while ((int_status = CSR_READ_1(sc, STATUS_REG)) & (Tx_Int | Rx_Int)) {
  576                 if (int_status & Rx_Int) {
  577                         CSR_WRITE_1(sc, STATUS_REG, Rx_Int);
  578                         handled = 1;
  579                         ex_rx_intr(sc);
  580                 } else if (int_status & Tx_Int) {
  581                         CSR_WRITE_1(sc, STATUS_REG, Tx_Int);
  582                         handled = 1;
  583                         ex_tx_intr(sc);
  584                         send_pkts = 1;
  585                 }
  586         }
  587 
  588         /*
  589          * If any packet has been transmitted, and there are queued packets to
  590          * be sent, attempt to send more packets to the network card.
  591          */
  592 
  593         if (send_pkts && ifq_empty(&ifp->if_snd) == 0)
  594                 ex_start(ifp);
  595 #ifdef EX_DEBUG
  596         exintr_count--;
  597 #endif
  598         DODEBUG(Start_End, printf("exintr: finish\n"););
  599 
  600         return handled;
  601 }
  602 
  603 void 
  604 ex_tx_intr(struct ex_softc *sc)
  605 {
  606         struct ifnet *ifp = &sc->arpcom.ac_if;
  607         int tx_status;
  608 
  609         DODEBUG(Start_End, printf("ex_tx_intr: start\n"););
  610         /*
  611          * - Cancel the watchdog.
  612          * For all packets transmitted since last transmit interrupt:
  613          * - Advance chain pointer to next queued packet.
  614          * - Update statistics.
  615          */
  616         ifp->if_timer = 0;
  617         while (sc->tx_head != sc->tx_tail) {
  618                 CSR_WRITE_2(sc, HOST_ADDR_REG, sc->tx_head);
  619                 if (!(CSR_READ_2(sc, IO_PORT_REG) & Done_bit))
  620                         break;
  621                 tx_status = CSR_READ_2(sc, IO_PORT_REG);
  622                 sc->tx_head = CSR_READ_2(sc, IO_PORT_REG);
  623                 if (!ISSET(tx_status, TX_OK_bit))
  624                         ifp->if_oerrors++;
  625                 ifp->if_collisions += tx_status & No_Collisions_bits;
  626         }
  627 
  628         /* The card should be ready to accept more packets now. */
  629         ifq_clr_oactive(&ifp->if_snd);
  630         DODEBUG(Status, printf("OIDLE tx_intr\n"););
  631 
  632         DODEBUG(Start_End, printf("ex_tx_intr: finish\n"););
  633 }
  634 
  635 void 
  636 ex_rx_intr(struct ex_softc *sc)
  637 {
  638         struct ifnet *ifp = &sc->arpcom.ac_if;
  639         struct mbuf_list ml = MBUF_LIST_INITIALIZER();
  640         int rx_status, pkt_len, QQQ;
  641         struct mbuf *m, *ipkt;
  642 
  643         DODEBUG(Start_End, printf("ex_rx_intr: start\n"););
  644         /*
  645          * For all packets received since last receive interrupt:
  646          * - If packet ok, read it into a new mbuf and queue it to interface,
  647          *   updating statistics.
  648          * - If packet bad, just discard it, and update statistics.
  649          * Finally, advance receive stop limit in card's memory to new location.
  650          */
  651         CSR_WRITE_2(sc, HOST_ADDR_REG, sc->rx_head);
  652         while (CSR_READ_2(sc, IO_PORT_REG) == RCV_Done) {
  653                 rx_status = CSR_READ_2(sc, IO_PORT_REG);
  654                 sc->rx_head = CSR_READ_2(sc, IO_PORT_REG);
  655                 QQQ = pkt_len = CSR_READ_2(sc, IO_PORT_REG);
  656                 if (rx_status & RCV_OK_bit) {
  657                         MGETHDR(m, M_DONTWAIT, MT_DATA);
  658                         ipkt = m;
  659                         if (ipkt == NULL)
  660                                 ifp->if_iqdrops++;
  661                         else {
  662                                 ipkt->m_pkthdr.len = pkt_len;
  663                                 ipkt->m_len = MHLEN;
  664                                 while (pkt_len > 0) {
  665                                         if (pkt_len >= MINCLSIZE) {
  666                                                 MCLGET(m, M_DONTWAIT);
  667                                                 if (m->m_flags & M_EXT)
  668                                                         m->m_len = MCLBYTES;
  669                                                 else {
  670                                                         m_freem(ipkt);
  671                                                         ifp->if_iqdrops++;
  672                                                         goto rx_another;
  673                                                 }
  674                                         }
  675                                         m->m_len = min(m->m_len, pkt_len);
  676                                         /*
  677                                          * NOTE: I'm assuming that all mbufs 
  678                                          * allocated are of even length, except
  679                                          * for the last one in an odd-length 
  680                                          * packet.
  681                                          */
  682                                         CSR_READ_MULTI_2(sc, IO_PORT_REG,
  683                                             mtod(m, caddr_t), m->m_len / 2);
  684                                         if (m->m_len & 1)
  685                                                 *(mtod(m, caddr_t) + 
  686                                                     m->m_len - 1) = 
  687                                                     CSR_READ_1(sc, IO_PORT_REG);
  688                                         pkt_len -= m->m_len;
  689                                         if (pkt_len > 0) {
  690                                                 MGET(m->m_next, M_DONTWAIT, 
  691                                                     MT_DATA);
  692                                         if (m->m_next == NULL) {
  693                                                 m_freem(ipkt);
  694                                                 ifp->if_iqdrops++;
  695                                                 goto rx_another;
  696                                         }
  697                                         m = m->m_next;
  698                                         m->m_len = MLEN;
  699                                 }
  700                         }
  701 #ifdef EX_DEBUG
  702                         if (debug_mask & Rcvd_Pkts) {
  703                                 if ((eh->ether_dhost[5] != 0xff) || 
  704                                     (eh->ether_dhost[0] != 0xff)) {
  705                                         printf("Receive packet with %d data bytes: %6D -> ", QQQ, eh->ether_shost, ":");
  706                                         printf("%6D\n", eh->ether_dhost, ":");
  707                                 } /* QQQ */
  708                         }
  709 #endif
  710                         ml_enqueue(&ml, ipkt);
  711                 }
  712         } else
  713                 ifp->if_ierrors++;
  714                 CSR_WRITE_2(sc, HOST_ADDR_REG, sc->rx_head);
  715                 rx_another: ;
  716         }
  717         if (sc->rx_head < sc->rx_lower_limit + 2)
  718                 CSR_WRITE_2(sc, RCV_STOP_REG, sc->rx_upper_limit);
  719         else
  720                 CSR_WRITE_2(sc, RCV_STOP_REG, sc->rx_head - 2);
  721 
  722         if_input(ifp, &ml);
  723 
  724         DODEBUG(Start_End, printf("ex_rx_intr: finish\n"););
  725 }       
  726 
  727 int 
  728 ex_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
  729 {
  730         struct ex_softc *sc = ifp->if_softc;
  731         struct ifreq *ifr = (struct ifreq *) data;
  732         int s, error = 0;
  733 
  734         DODEBUG(Start_End, printf("ex_ioctl: start "););
  735 
  736         s = splnet();
  737 
  738         switch(cmd) {
  739         case SIOCSIFADDR:
  740                 DODEBUG(Start_End, printf("SIOCSIFADDR"););
  741                 ifp->if_flags |= IFF_UP;
  742                 if (!(ifp->if_flags & IFF_RUNNING))
  743                         ex_init(sc);
  744                 break;
  745         case SIOCSIFFLAGS:
  746                 DODEBUG(Start_End, printf("SIOCSIFFLAGS"););
  747                 if ((ifp->if_flags & IFF_UP) == 0 && ifp->if_flags & IFF_RUNNING) {
  748                         ifp->if_flags &= ~IFF_RUNNING;
  749                         ex_stop(sc);
  750                 } else
  751                         ex_init(sc);
  752                 break;
  753         case SIOCSIFMEDIA:
  754         case SIOCGIFMEDIA:
  755                 error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, cmd);
  756                 break;
  757         default:
  758                 error = ether_ioctl(ifp, &sc->arpcom, cmd, data);
  759         }
  760 
  761         if (error == ENETRESET) {
  762                 if (ifp->if_flags & IFF_RUNNING)
  763                         ex_init(sc);
  764                 error = 0;
  765         }
  766 
  767         splx(s);
  768         DODEBUG(Start_End, printf("\nex_ioctl: finish\n"););
  769         return(error);
  770 }
  771 
  772 void
  773 ex_setmulti(struct ex_softc *sc)
  774 {
  775         struct arpcom *ac = &sc->arpcom;
  776         struct ifnet *ifp = &sc->arpcom.ac_if;
  777         struct ether_multi *enm;
  778         struct ether_multistep step;
  779         uint16_t *addr;
  780         int count, timeout, status;
  781 
  782         ifp->if_flags &= ~IFF_ALLMULTI;
  783 
  784         count = 0;
  785         ETHER_FIRST_MULTI(step, ac, enm);
  786         while (enm != NULL) {
  787                 count++;
  788                 ETHER_NEXT_MULTI(step, enm);
  789         }
  790 
  791         if (count > 63 || ac->ac_multirangecnt > 0)
  792                 ifp->if_flags |= IFF_ALLMULTI;
  793 
  794         if (ifp->if_flags & IFF_PROMISC || ifp->if_flags & IFF_ALLMULTI) {
  795                 /*
  796                  * Interface is in promiscuous mode, there are too many
  797                  * multicast addresses for the card to handle or there
  798                  * is a multicast range
  799                  */
  800                 CSR_WRITE_1(sc, CMD_REG, Bank2_Sel);
  801                 CSR_WRITE_1(sc, REG2, CSR_READ_1(sc, REG2) | Promisc_Mode);
  802                 CSR_WRITE_1(sc, REG3, CSR_READ_1(sc, REG3));
  803                 CSR_WRITE_1(sc, CMD_REG, Bank0_Sel);
  804         } else if (ifp->if_flags & IFF_MULTICAST && count > 0) {
  805                 /* Program multicast addresses plus our MAC address
  806                  * into the filter */
  807                 CSR_WRITE_1(sc, CMD_REG, Bank2_Sel);
  808                 CSR_WRITE_1(sc, REG2, CSR_READ_1(sc, REG2) | Multi_IA);
  809                 CSR_WRITE_1(sc, REG3, CSR_READ_1(sc, REG3));
  810                 CSR_WRITE_1(sc, CMD_REG, Bank0_Sel);
  811 
  812                 /* Borrow space from TX buffer; this should be safe
  813                  * as this is only called from ex_init */
  814                 
  815                 CSR_WRITE_2(sc, HOST_ADDR_REG, sc->tx_lower_limit);
  816                 CSR_WRITE_2(sc, IO_PORT_REG, MC_Setup_CMD);
  817                 CSR_WRITE_2(sc, IO_PORT_REG, 0);
  818                 CSR_WRITE_2(sc, IO_PORT_REG, 0);
  819                 CSR_WRITE_2(sc, IO_PORT_REG, (count + 1) * 6);
  820 
  821                 ETHER_FIRST_MULTI(step, ac, enm);
  822                 while (enm != NULL) {
  823                         addr = (uint16_t*)enm->enm_addrlo;
  824                         CSR_WRITE_2(sc, IO_PORT_REG, *addr++);
  825                         CSR_WRITE_2(sc, IO_PORT_REG, *addr++);
  826                         CSR_WRITE_2(sc, IO_PORT_REG, *addr++);
  827                         ETHER_NEXT_MULTI(step, enm);
  828                 }
  829 
  830                 /* Program our MAC address as well */
  831                 /* XXX: Is this necessary?  The Linux driver does this
  832                  * but the NetBSD driver does not */
  833                 addr = (uint16_t*) sc->arpcom.ac_enaddr;
  834                 CSR_WRITE_2(sc, IO_PORT_REG, *addr++);
  835                 CSR_WRITE_2(sc, IO_PORT_REG, *addr++);
  836                 CSR_WRITE_2(sc, IO_PORT_REG, *addr++);
  837 
  838                 CSR_READ_2(sc, IO_PORT_REG);
  839                 CSR_WRITE_2(sc, XMT_BAR, sc->tx_lower_limit);
  840                 CSR_WRITE_1(sc, CMD_REG, MC_Setup_CMD);
  841 
  842                 sc->tx_head = sc->tx_lower_limit;
  843                 sc->tx_tail = sc->tx_head + XMT_HEADER_LEN + (count + 1) * 6;
  844 
  845                 for (timeout = 0; timeout < 100; timeout++) {
  846                         DELAY(2);
  847                         if ((CSR_READ_1(sc, STATUS_REG) & Exec_Int) == 0)
  848                                 continue;
  849 
  850                         status = CSR_READ_1(sc, CMD_REG);
  851                         CSR_WRITE_1(sc, STATUS_REG, Exec_Int);
  852                         break;
  853                 }
  854 
  855                 sc->tx_head = sc->tx_tail;
  856         } else {
  857                 /* No multicast or promiscuous mode */
  858                 CSR_WRITE_1(sc, CMD_REG, Bank2_Sel);
  859                 CSR_WRITE_1(sc, REG2, CSR_READ_1(sc, REG2) & 0xDE);
  860                         /* ~(Multi_IA | Promisc_Mode) */
  861                 CSR_WRITE_1(sc, REG3, CSR_READ_1(sc, REG3));
  862                 CSR_WRITE_1(sc, CMD_REG, Bank0_Sel);
  863         }
  864 }
  865 
  866 void 
  867 ex_reset(struct ex_softc *sc)
  868 {
  869         int s;
  870 
  871         DODEBUG(Start_End, printf("ex_reset: start\n"););
  872   
  873         s = splnet();
  874         ex_stop(sc);
  875         ex_init(sc);
  876         splx(s);
  877 
  878         DODEBUG(Start_End, printf("ex_reset: finish\n"););
  879 }
  880 
  881 void 
  882 ex_watchdog(struct ifnet *ifp)
  883 {
  884         struct ex_softc *sc = ifp->if_softc;
  885 
  886         DODEBUG(Start_End, printf("ex_watchdog: start\n"););
  887 
  888         ifq_clr_oactive(&ifp->if_snd);
  889         DODEBUG(Status, printf("OIDLE watchdog\n"););
  890         ifp->if_oerrors++;
  891         ex_reset(sc);
  892         ex_start(ifp);
  893 
  894         DODEBUG(Start_End, printf("ex_watchdog: finish\n"););
  895 }
  896 
  897 uint64_t
  898 ex_get_media(struct ex_softc *sc)
  899 {
  900         int     current, media;
  901 
  902         media = ex_eeprom_read(sc, EE_W5);
  903 
  904         CSR_WRITE_1(sc, CMD_REG, Bank2_Sel);
  905         current = CSR_READ_1(sc, REG3);
  906         CSR_WRITE_1(sc, CMD_REG, Bank0_Sel);
  907 
  908         if ((current & TPE_bit) && (media & EE_W5_PORT_TPE))
  909                 return(IFM_ETHER|IFM_10_T);
  910         if ((current & BNC_bit) && (media & EE_W5_PORT_BNC))
  911                 return(IFM_ETHER|IFM_10_2);
  912 
  913         if (media & EE_W5_PORT_AUI)
  914                 return (IFM_ETHER|IFM_10_5);
  915 
  916         return (IFM_ETHER|IFM_AUTO);
  917 }
  918 
  919 int
  920 ex_ifmedia_upd (struct ifnet *ifp)
  921 {
  922         struct ex_softc *sc = ifp->if_softc;
  923 
  924         if (IFM_TYPE(sc->ifmedia.ifm_media) != IFM_ETHER)
  925                 return (EINVAL);
  926 
  927         return (0);
  928 }
  929 
  930 void
  931 ex_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
  932 {
  933         struct ex_softc *sc = ifp->if_softc;
  934 
  935         ifmr->ifm_status = IFM_AVALID | IFM_ACTIVE;
  936         ifmr->ifm_active = ex_get_media(sc);
  937 }
  938 
  939 u_short 
  940 ex_eeprom_read(struct ex_softc *sc, int location)
  941 {
  942         int i;
  943         u_short data = 0;
  944         int read_cmd = location | EE_READ_CMD;
  945         short ctrl_val = EECS;
  946 
  947         CSR_WRITE_1(sc, CMD_REG, Bank2_Sel);
  948         CSR_WRITE_1(sc, EEPROM_REG, EECS);
  949         for (i = 8; i >= 0; i--) {
  950                 short outval = (read_cmd & (1 << i)) ? ctrl_val | EEDI : 
  951                     ctrl_val;
  952                 CSR_WRITE_1(sc, EEPROM_REG, outval);
  953                 CSR_WRITE_1(sc, EEPROM_REG, outval | EESK);
  954                 delay(3);
  955                 CSR_WRITE_1(sc, EEPROM_REG, outval);
  956                 delay(2);
  957         }
  958         CSR_WRITE_1(sc, EEPROM_REG, ctrl_val);
  959         for (i = 16; i > 0; i--) {
  960                 CSR_WRITE_1(sc, EEPROM_REG, ctrl_val | EESK);
  961                 delay(3);
  962                 data = (data << 1) | ((CSR_READ_1(sc, EEPROM_REG) & EEDO) ? 1 : 0);
  963                 CSR_WRITE_1(sc, EEPROM_REG, ctrl_val);
  964                 delay(2);
  965         }
  966         ctrl_val &= ~EECS;
  967         CSR_WRITE_1(sc, EEPROM_REG, ctrl_val | EESK);
  968         delay(3);
  969         CSR_WRITE_1(sc, EEPROM_REG, ctrl_val);
  970         delay(2);
  971         CSR_WRITE_1(sc, CMD_REG, Bank0_Sel);
  972         return(data);
  973 }

Cache object: 3d1d6201150337cd46cf32301d12846a


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.