root/dev/isa/if_ex.c

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

DEFINITIONS

This source file includes following definitions.
  1. look_for_card
  2. ex_probe
  3. ex_attach
  4. ex_init
  5. ex_start
  6. ex_stop
  7. exintr
  8. ex_tx_intr
  9. ex_rx_intr
  10. ex_ioctl
  11. ex_reset
  12. ex_watchdog
  13. eeprom_read

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

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