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/i386/isa/if_zp.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 /*
    2  * This code is based on
    3  *  (1) FreeBSD implementation on ISA/EISA Ethelink III by Herb Peyerl
    4  *  (2) Linux implementation on PCMCIA Etherlink III by Devid Hinds
    5  *  (3) FreeBSD implementation on PCMCIA IBM Ethernet Card I/II
    6  *      by David Greenman
    7  *  (4) RT-Mach implementation on PCMCIA/ISA/EISA Etherlink III
    8  *      by Seiji Murata
    9  *
   10  *  Copyright (c) by HOSOKAWA, Tatsumi <hosokawa@mt.cs.keio.ac.jp>
   11  *  Copyright (c) by Seiji Murata <seiji@mt.cs.keio.ac.jp>
   12  */
   13 /*
   14  * Copyright (c) 1993 Herb Peyerl <hpeyerl@novatel.ca>
   15  * All rights reserved.
   16  *
   17  * Redistribution and use in source and binary forms, with or without
   18  * modification, are permitted provided that the following conditions
   19  * are met:
   20  * 1. Redistributions of source code must retain the above copyright
   21  *    notice, this list of conditions and the following disclaimer.
   22  * 2. The name of the author may not be used to endorse or promote products
   23  *    derived from this software without specific prior written permission
   24  *
   25  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   26  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   27  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   28  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   29  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   30  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   31  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   32  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   33  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   34  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   35  *
   36  *      From: if_ep.c,v 1.9 1994/01/25 10:46:29 deraadt Exp $
   37  * $FreeBSD: src/sys/i386/isa/if_zp.c,v 1.26.2.8 1999/09/05 08:13:01 peter Exp $
   38  */
   39 /*-
   40  * TODO:
   41  * [1] integrate into current if_ed.c
   42  * [2] parse tuples to find out where to map the shared memory buffer,
   43  *     and what to write into the configuration register
   44  * [3] move pcic-specific code into a separate module.
   45  *
   46  * Device driver for IBM PCMCIA Credit Card Adapter for Ethernet,
   47  * if_ze.c
   48  *
   49  * Based on the Device driver for National Semiconductor DS8390 ethernet
   50  * adapters by David Greenman.  Modifications for PCMCIA by Keith Moore.
   51  * Adapted for FreeBSD 1.1.5 by Jordan Hubbard.
   52  *
   53  * Currently supports only the IBM Credit Card Adapter for Ethernet, but
   54  * could probably work with other PCMCIA cards also, if it were modified
   55  * to get the locations of the PCMCIA configuration option register (COR)
   56  * by parsing the configuration tuples, rather than by hard-coding in
   57  * the value expected by IBM's card.
   58  *
   59  * Sources for data on the PCMCIA/IBM CCAE specific portions of the driver:
   60  *
   61  * [1] _Local Area Network Credit Card Adapters Technical Reference_,
   62  *     IBM Corp., SC30-3585-00, part # 33G9243.
   63  * [2] "pre-alpha" PCMCIA support code for Linux by Barry Jaspan.
   64  * [3] Intel 82536SL PC Card Interface Controller Data Sheet, Intel
   65  *     Order Number 290423-002
   66  * [4] National Semiconductor DP83902A ST-NIC (tm) Serial Network
   67  *     Interface Controller for Twisted Pair data sheet.
   68  *
   69  *
   70  * Copyright (C) 1993, David Greenman. This software may be used, modified,
   71  *   copied, distributed, and sold, in both source and binary form provided
   72  *   that the above copyright and these terms are retained. Under no
   73  *   circumstances is the author responsible for the proper functioning
   74  *   of this software, nor does the author assume any responsibility
   75  *   for damages incurred with its use.
   76  */
   77 /*======================================================================
   78 
   79     A PCMCIA ethernet driver for the 3com 3c589 card.
   80 
   81     Written by David Hinds, dhinds@allegro.stanford.edu
   82 
   83     The network driver code is based on Donald Becker's 3c589 code:
   84 
   85     Written 1994 by Donald Becker.
   86     Copyright 1993 United States Government as represented by the
   87     Director, National Security Agency.  This software may be used and
   88     distributed according to the terms of the GNU Public License,
   89     incorporated herein by reference.
   90     Donald Becker may be reached at becker@cesdis1.gsfc.nasa.gov
   91 
   92 ======================================================================*/
   93 /*
   94  * I doubled delay loops in this file because it is not enough for some
   95  * laptop machines' PCIC (especially, on my Chaplet ILFA 350 ^^;).
   96  *                        HOSOKAWA, Tatsumi <hosokawa@mt.cs.keio.ac.jp>
   97  */
   98 /*
   99  * Very small patch for IBM Ethernet PCMCIA Card II and IBM ThinkPad230Cs.
  100  *                      ETO, Toshihisa <eto@osl.fujitsu.co.jp>
  101  */
  102 
  103 /* XXX - Don't mix different PCCARD support code */
  104 #include "card.h"
  105 #include "pcic.h"
  106 #if NCARD > 0 || NPCIC > 0
  107 #ifndef LINT_PCCARD_HACK
  108 #error "Dedicated PCMCIA drivers and generic PCMCIA support can't be mixed"
  109 #else
  110 #warning "Dedicated PCMCIA drivers and generic PCMCIA support can't be mixed"
  111 #endif
  112 #endif
  113 
  114 #include "zp.h"
  115 
  116 #include "bpfilter.h"
  117 
  118 #include <sys/param.h>
  119 #if defined(__FreeBSD__)
  120 #include <sys/systm.h>
  121 #include <sys/conf.h>
  122 #include <sys/kernel.h>
  123 #endif
  124 #include <sys/mbuf.h>
  125 #include <sys/socket.h>
  126 #include <sys/ioctl.h>
  127 #include <sys/errno.h>
  128 #include <sys/syslog.h>
  129 
  130 #include <net/if.h>
  131 #include <net/if_dl.h>
  132 #include <net/if_types.h>
  133 
  134 #ifdef INET
  135 #include <netinet/in.h>
  136 #include <netinet/in_systm.h>
  137 #include <netinet/in_var.h>
  138 #include <netinet/ip.h>
  139 #include <netinet/if_ether.h>
  140 #endif
  141 
  142 #ifdef IPX
  143 #include <netipx/ipx.h>
  144 #include <netipx/ipx_if.h>
  145 #endif
  146 
  147 #ifdef NS
  148 #include <netns/ns.h>
  149 #include <netns/ns_if.h>
  150 #endif
  151 
  152 #if NBPFILTER > 0
  153 #include <net/bpf.h>
  154 #include <net/bpfdesc.h>
  155 #endif
  156 
  157 #include <machine/clock.h>
  158 #include <machine/md_var.h>
  159 
  160 #include <i386/isa/isa_device.h>
  161 #include <i386/isa/if_zpreg.h>
  162 #include <i386/isa/pcic.h>
  163 
  164 #include "apm.h"
  165 #if NAPM > 0
  166 #include <machine/apm_bios.h>
  167 #endif                          /* NAPM > 0 */
  168 
  169 
  170 /*****************************************************************************
  171  *                       Driver for Ethernet Adapter                         *
  172  *****************************************************************************/
  173 /*
  174  * zp_softc: per line info and status
  175  */
  176 static struct zp_softc {
  177         struct arpcom arpcom;   /* Ethernet common part          */
  178 #define MAX_MBS  8              /* # of mbufs we keep around     */
  179         struct mbuf *mb[MAX_MBS];       /* spare mbuf storage.           */
  180         int     next_mb;        /* Which mbuf to use next.       */
  181         int     last_mb;        /* Last mbuf.                    */
  182         int     ep_io_addr;     /* i/o bus address               */
  183         char    ep_connectors;  /* Connectors on this card.      */
  184         int     tx_start_thresh;/* Current TX_start_thresh.      */
  185         char    bus32bit;       /* 32bit access possible         */
  186         u_short if_port;
  187         u_char  last_alive;     /* information for reconfiguration */
  188         u_char  last_up;        /* information for reconfiguration */
  189         int     slot;           /* PCMCIA slot */
  190 #if NAPM >              0
  191         struct apmhook s_hook;  /* reconfiguration support */
  192         struct apmhook r_hook;  /* reconfiguration support */
  193 #endif                          /* NAPM > 0 */
  194 }       zp_softc[NZP];
  195 
  196 static int zpprobe __P((struct isa_device *));
  197 static int zpattach __P((struct isa_device *));
  198 static int zp_suspend __P((void *visa_dev));
  199 static int zp_resume __P((void *visa_dev));
  200 static int zpioctl __P((struct ifnet * ifp, int, caddr_t));
  201 static u_short read_eeprom_data __P((int, int));
  202 
  203 static void zpinit __P((int));
  204 static void zpmbuffill __P((void *));
  205 static void zpmbufempty __P((struct zp_softc *));
  206 static void zpread __P((struct zp_softc *));
  207 static void zpreset __P((int));
  208 static void zpstart __P((struct ifnet *));
  209 static void zpstop __P((int));
  210 static void zpwatchdog __P((struct ifnet *));
  211 
  212 struct isa_driver zpdriver = {
  213         zpprobe,
  214         zpattach,
  215         "zp"
  216 };
  217 #define CARD_INFO  "3Com Corporation~3C589"
  218 
  219 static unsigned char card_info[256];
  220 
  221 /*
  222  * scan the card information structure looking for the version/product info
  223  * tuple.  when we find it, compare it to the string we are looking for.
  224  * return 1 if we find it, 0 otherwise.
  225  */
  226 
  227 static int
  228 zp_check_cis(unsigned char *scratch)
  229 {
  230         int     i, j, k;
  231 
  232         card_info[0] = '\0';
  233         i = 0;
  234         while (scratch[i] != 0xff && i < 1024) {
  235                 unsigned char link = scratch[i + 2];
  236 
  237                 if (scratch[i] == 0x15) {
  238                         /* level 1 version/product info copy to card_info,
  239                          * translating '\0' to '~' */
  240                         k = 0;
  241                         for (j = i + 8; scratch[j] != 0xff; j += 2)
  242                                 card_info[k++] = scratch[j] == '\0' ? '~' : scratch[j];
  243                         card_info[k++] = '\0';
  244                         return (bcmp(card_info, CARD_INFO, sizeof(CARD_INFO) - 1) == 0);
  245                 }
  246                 i += 4 + 2 * link;
  247         }
  248         return 0;
  249 }
  250 /*
  251  * Probe each slot looking for an IBM Credit Card Adapter for Ethernet
  252  * For each card that we find, map its card information structure
  253  * into system memory at 'scratch' and see whether it's one of ours.
  254  * Return the slot number if we find a card, or -1 otherwise.
  255  *
  256  * Side effects:
  257  * + On success, leaves CIS mapped into memory at 'scratch';
  258  *   caller must free it.
  259  * + On success, leaves ethernet address in enet_addr.
  260  * + Leaves product/vendor id of last card probed in 'card_info'
  261  */
  262 
  263 static int     prev_slot = 0;
  264 
  265 static int
  266 zp_find_adapter(unsigned char *scratch, int reconfig)
  267 {
  268         int     slot;
  269 
  270         for (slot = prev_slot; slot < MAXSLOT; ++slot) {
  271                 /* see if there's a PCMCIA controller here Intel PCMCIA
  272                  * controllers use 0x82 and 0x83 IBM clone chips use 0x88 and
  273                  * 0x89, apparently */
  274                 /* IBM ThinkPad230Cs use 0x84. */
  275                 unsigned char idbyte = pcic_getb(slot, PCIC_ID_REV);
  276 
  277                 if (idbyte != 0x82 && idbyte != 0x83 &&
  278                     idbyte != 0x84 &&   /* for IBM ThinkPad 230Cs */
  279                     idbyte != 0x88 && idbyte != 0x89) {
  280                         continue;
  281                 }
  282                 if ((pcic_getb(slot, PCIC_STATUS) & PCIC_CD) != PCIC_CD) {
  283                         if (!reconfig) {
  284                                 printf("zp: slot %d: no card in slot\n", slot);
  285                         } else {
  286                                 log(LOG_NOTICE, "zp: slot %d: no card in slot\n", slot);
  287                         }
  288                         /* no card in slot */
  289                         continue;
  290                 }
  291                 pcic_power_on(slot);
  292                 pcic_reset(slot);
  293                 DELAY(50000);
  294                 /* map the card's attribute memory and examine its card
  295                  * information structure tuples for something we recognize. */
  296                 pcic_map_memory(slot, 0, kvtop(scratch), 0L,
  297                     0xFFFL, ATTRIBUTE, 1);
  298 
  299                 if ((zp_check_cis(scratch)) > 0) {
  300                         /* found it */
  301                         if (!reconfig) {
  302                                 printf("zp: found card in slot %d\n", slot);
  303                         } else {
  304                                 log(LOG_NOTICE, "zp: found card in slot %d\n", slot);
  305                         }
  306                         prev_slot = (prev_slot == MAXSLOT - 1) ? 0 : prev_slot + 1;
  307 
  308                         return slot;
  309                 } else {
  310                         if (!reconfig) {
  311                                 printf("zp: pcmcia slot %d: %s\n", slot, card_info);
  312                         } else {
  313                                 log(LOG_NOTICE, "zp: pcmcia slot %d: %s\n", slot, card_info);
  314                         }
  315                 }
  316                 pcic_unmap_memory(slot, 0);
  317         }
  318         prev_slot = 0;
  319         return -1;
  320 }
  321 
  322 
  323 /*
  324  * macros to handle casting unsigned long to (char *) so we can
  325  * read/write into physical memory space.
  326  */
  327 
  328 #define PEEK(addr) (*((unsigned char *)(addr)))
  329 #define POKE(addr,val) do { PEEK(addr) = (val); } while (0)
  330 
  331 /*
  332  * Determine if the device is present
  333  *
  334  *   on entry:
  335  *      a pointer to an isa_device struct
  336  *   on exit:
  337  *      NULL if device not found
  338  *      or # of i/o addresses used (if found)
  339  */
  340 static int
  341 zpprobe(struct isa_device * isa_dev)
  342 {
  343         struct zp_softc *sc = &zp_softc[isa_dev->id_unit];
  344         int     slot;
  345         u_short k;
  346         int     re_init_flag;
  347 
  348         if ((slot = zp_find_adapter(isa_dev->id_maddr, isa_dev->id_reconfig)) < 0)
  349                 return 0;
  350 
  351         /* okay, we found a card, so set it up */
  352         /* Inhibit 16 bit memory delay. POINTETH.SYS apparently does this, for
  353          * what reason I don't know. */
  354         pcic_putb(slot, PCIC_CDGC,
  355             pcic_getb(slot, PCIC_CDGC) | PCIC_16_DL_INH);
  356         /* things to map (1) card's EEPROM is already mapped by the
  357          * find_adapter routine but we still need to get the card's ethernet
  358          * address. after that we unmap that part of attribute memory. (2)
  359          * card configuration registers need to be mapped in so we can set the
  360          * configuration and socket # registers. (3) shared memory packet
  361          * buffer (4) i/o ports (5) IRQ */
  362 #ifdef  notdef
  363         /* Sigh.  Location of the ethernet address isn't documented in [1]. It
  364          * was derived by doing a hex dump of all of attribute memory and
  365          * looking for the IBM vendor prefix. */
  366         enet_addr[0] = PEEK(isa_dev->id_maddr + 0xff0);
  367         enet_addr[1] = PEEK(isa_dev->id_maddr + 0xff2);
  368         enet_addr[2] = PEEK(isa_dev->id_maddr + 0xff4);
  369         enet_addr[3] = PEEK(isa_dev->id_maddr + 0xff6);
  370         enet_addr[4] = PEEK(isa_dev->id_maddr + 0xff8);
  371         enet_addr[5] = PEEK(isa_dev->id_maddr + 0xffa);
  372 #endif
  373         re_init_flag = 0;
  374 re_init:
  375         /* (2) map card configuration registers.  these are offset in card
  376          * memory space by 0x20000.  normally we could get this offset from
  377          * the card information structure, but I'm too lazy and am not quite
  378          * sure if I understand the CIS anyway.
  379          * 
  380          * XXX IF YOU'RE TRYING TO PORT THIS DRIVER FOR A DIFFERENT PCMCIA CARD,
  381          * the most likely thing to change is the constant 0x20000 in the next
  382          * statement.  Oh yes, also change the card id string that we probe
  383          * for. */
  384         pcic_map_memory(slot, 0, kvtop(isa_dev->id_maddr), 0x10000, 8L,
  385             ATTRIBUTE, 1);
  386 #if OLD_3C589B_CARDS
  387         POKE(isa_dev->id_maddr, 0x80);  /* reset the card (how long?) */
  388         DELAY(40000);
  389 #endif
  390         /* Set the configuration index.  According to [1], the adapter won't
  391          * respond to any i/o signals until we do this; it uses the Memory
  392          * Only interface (whatever that is; it's not documented). Also turn
  393          * on "level" (not pulse) interrupts.
  394          * 
  395          * XXX probably should init the socket and copy register also, so that we
  396          * can deal with multiple instances of the same card. */
  397         POKE(isa_dev->id_maddr, 0x41);
  398         pcic_unmap_memory(slot, 0);
  399 
  400         /* (4) map i/o ports.
  401          * 
  402          * XXX is it possible that the config file leaves this unspecified, in
  403          * which case we have to pick one?
  404          * 
  405          * At least one PCMCIA device driver I'v seen maps a block of 32
  406          * consecutive i/o ports as two windows of 16 ports each. Maybe some
  407          * other pcic chips are restricted to 16-port windows; the 82365SL
  408          * doesn't seem to have that problem.  But since we have an extra
  409          * window anyway... */
  410         pcic_map_io(slot, 0, isa_dev->id_iobase, 16, 2);
  411 
  412         /* (5) configure the card for the desired interrupt
  413          * 
  414          * XXX is it possible that the config file leaves this unspecified? */
  415         pcic_map_irq(slot, ffs(isa_dev->id_irq) - 1);
  416 
  417         /* tell the PCIC that this is an I/O card (not memory) */
  418         pcic_putb(slot, PCIC_INT_GEN,
  419             pcic_getb(slot, PCIC_INT_GEN) | PCIC_CARDTYPE);
  420 
  421         sc->ep_io_addr = isa_dev->id_iobase;
  422         GO_WINDOW(0);
  423         k = read_eeprom_data(BASE, EEPROM_ADDR_CFG);    /* get addr cfg */
  424         sc->if_port = k >> 14;
  425         k = (k & 0x1f) * 0x10 + 0x200;  /* decode base addr. */
  426         if (k != (u_short) isa_dev->id_iobase) {
  427                 if (!re_init_flag) {
  428                         re_init_flag++;
  429                         goto re_init;
  430                 }
  431                 return (0);
  432         }
  433         k = read_eeprom_data(BASE, EEPROM_RESOURCE_CFG);
  434 
  435         k >>= 12;
  436 
  437         if (isa_dev->id_irq != (1 << ((k == 2) ? 9 : k)))
  438                 return (0);
  439 
  440         outb(BASE, ACTIVATE_ADAPTER_TO_CONFIG);
  441 
  442 
  443         /* information for reconfiguration */
  444         sc->last_alive = 0;
  445         sc->last_up = 0;
  446         sc->slot = slot;
  447 
  448         return (0x10);          /* 16 bytes of I/O space used. */
  449 }
  450 #if NAPM > 0
  451 static int
  452 zp_suspend(visa_dev)
  453         void   *visa_dev;
  454 {
  455 #if 0
  456         struct isa_device *isa_dev = visa_dev;
  457         struct zp_softc *sc = &zp_softc[isa_dev->id_unit];
  458 
  459         pcic_power_off(sc->slot);
  460 #endif
  461         return 0;
  462 }
  463 
  464 static int
  465 zp_resume(visa_dev)
  466         void   *visa_dev;
  467 {
  468         struct isa_device *isa_dev = visa_dev;
  469 
  470         prev_slot = 0;
  471         reconfig_isadev(isa_dev, &net_imask);
  472         return 0;
  473 }
  474 #endif                          /* NAPM > 0 */
  475 
  476 
  477 /*
  478  * Install interface into kernel networking data structures
  479  */
  480 
  481 static int
  482 zpattach(isa_dev)
  483         struct isa_device *isa_dev;
  484 {
  485         struct zp_softc *sc = &zp_softc[isa_dev->id_unit];
  486         struct ifnet *ifp = &sc->arpcom.ac_if;
  487         u_short i;
  488         int     pl;
  489 
  490         /* PCMCIA card can be offlined. Reconfiguration is required */
  491         if (isa_dev->id_reconfig) {
  492                 if (!isa_dev->id_alive && sc->last_alive) {
  493                         pl = splimp();
  494                         sc->last_up = (ifp->if_flags & IFF_UP);
  495                         if_down(ifp);
  496                         splx(pl);
  497                         sc->last_alive = 0;
  498                 }
  499                 if (isa_dev->id_alive && !sc->last_alive) {
  500                         zpreset(isa_dev->id_unit);
  501                         if (sc->last_up) {
  502                                 pl = splimp();
  503                                 if_up(ifp);
  504                                 splx(pl);
  505                         }
  506                         sc->last_alive = 1;
  507                 }
  508                 return 1;
  509         } else {
  510                 sc->last_alive = 1;
  511         }
  512 
  513 
  514         sc->ep_io_addr = isa_dev->id_iobase;
  515         printf("zp%d: ", isa_dev->id_unit);
  516 
  517         sc->ep_connectors = 0;
  518 
  519         i = inw(isa_dev->id_iobase + EP_W0_CONFIG_CTRL);
  520 
  521         if (i & IS_AUI) {
  522                 printf("aui");
  523                 sc->ep_connectors |= AUI;
  524         }
  525         if (i & IS_BNC) {
  526                 if (sc->ep_connectors)
  527                         printf("/");
  528                 printf("bnc");
  529                 sc->ep_connectors |= BNC;
  530         }
  531         if (i & IS_UTP) {
  532                 if (sc->ep_connectors)
  533                         printf("/");
  534                 printf("utp");
  535                 sc->ep_connectors |= UTP;
  536         }
  537         if (!sc->ep_connectors)
  538                 printf("no connectors!");
  539 
  540         GO_WINDOW(0);
  541         {
  542                 short   tmp_addr[3];
  543                 int     i;
  544                 for (i = 0; i < 3; i++) {
  545                         tmp_addr[i] = htons(read_eeprom_data(BASE, i));
  546                 }
  547                 bcopy(tmp_addr, sc->arpcom.ac_enaddr, 6);
  548         }
  549 
  550         printf(" address %6D\n", sc->arpcom.ac_enaddr, ":");
  551 
  552         ifp->if_softc = sc;
  553         ifp->if_mtu = ETHERMTU;
  554         ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
  555         ifp->if_unit = isa_dev->id_unit;
  556         ifp->if_name = "zp";
  557         ifp->if_output = ether_output;
  558         ifp->if_start = zpstart;
  559         ifp->if_ioctl = zpioctl;
  560         ifp->if_watchdog = zpwatchdog;
  561         /* Select connector according to board setting. */
  562         ifp->if_flags |= IFF_LINK0;
  563 
  564         if_attach(ifp);
  565         ether_ifattach(ifp);
  566 
  567 #if NBPFILTER > 0
  568         bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header));
  569 #endif
  570 #if NAPM > 0
  571         sc->s_hook.ah_fun = zp_suspend;
  572         sc->s_hook.ah_arg = (void *) isa_dev;
  573         sc->s_hook.ah_name = "3Com PCMCIA Etherlink III 3C589";
  574         sc->s_hook.ah_order = APM_MID_ORDER;
  575         apm_hook_establish(APM_HOOK_SUSPEND, &sc->s_hook);
  576         sc->r_hook.ah_fun = zp_resume;
  577         sc->r_hook.ah_arg = (void *) isa_dev;
  578         sc->r_hook.ah_name = "3Com PCMCIA Etherlink III 3C589";
  579         sc->r_hook.ah_order = APM_MID_ORDER;
  580         apm_hook_establish(APM_HOOK_RESUME, &sc->r_hook);
  581 #endif                          /* NAPM > 0 */
  582         return 1;
  583 }
  584 /*
  585  * The order in here seems important. Otherwise we may not receive
  586  * interrupts. ?!
  587  */
  588 static void
  589 zpinit(unit)
  590         int     unit;
  591 {
  592         register struct zp_softc *sc = &zp_softc[unit];
  593         register struct ifnet *ifp = &sc->arpcom.ac_if;
  594         int     s, i;
  595 
  596         if (ifp->if_addrlist == (struct ifaddr *) 0)
  597                 return;
  598 
  599         s = splimp();
  600         while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS);
  601 
  602         GO_WINDOW(0);
  603 
  604         /* Disable the card */
  605         outw(BASE + EP_W0_CONFIG_CTRL, 0);
  606 
  607         /* Enable the card */
  608         outw(BASE + EP_W0_CONFIG_CTRL, ENABLE_DRQ_IRQ);
  609 
  610         GO_WINDOW(2);
  611 
  612         /* Reload the ether_addr. */
  613         for (i = 0; i < 6; i++)
  614                 outb(BASE + EP_W2_ADDR_0 + i, sc->arpcom.ac_enaddr[i]);
  615 
  616         outw(BASE + EP_COMMAND, RX_RESET);
  617         outw(BASE + EP_COMMAND, TX_RESET);
  618 
  619         /* Window 1 is operating window */
  620         GO_WINDOW(1);
  621         for (i = 0; i < 31; i++)
  622                 inb(BASE + EP_W1_TX_STATUS);
  623 
  624         /* get rid of stray intr's */
  625         outw(BASE + EP_COMMAND, ACK_INTR | 0xff);
  626 
  627         outw(BASE + EP_COMMAND, SET_RD_0_MASK | S_CARD_FAILURE | S_RX_COMPLETE |
  628             S_TX_COMPLETE | S_TX_AVAIL);
  629         outw(BASE + EP_COMMAND, SET_INTR_MASK | S_CARD_FAILURE | S_RX_COMPLETE |
  630             S_TX_COMPLETE | S_TX_AVAIL);
  631 
  632 #ifndef IFF_MULTICAST
  633 #define IFF_MULTICAST   0x10000
  634 #endif
  635 
  636         outw(BASE + EP_COMMAND, SET_RX_FILTER | FIL_INDIVIDUAL |
  637             ((sc->arpcom.ac_if.if_flags & IFF_MULTICAST) ? FIL_GROUP : 0) |
  638             FIL_BRDCST |
  639             ((sc->arpcom.ac_if.if_flags & IFF_PROMISC) ? FIL_ALL : 0));
  640         /* you can `ifconfig (link0|-link0) ep0' to get the following
  641          * behaviour: -link0    disable AUI/UTP. enable BNC. link0 disable
  642          * BNC. enable AUI. if the card has a UTP connector, that is enabled
  643          * too. not sure, but it seems you have to be careful to not plug
  644          * things into both AUI & UTP. */
  645 
  646         if (!(ifp->if_flags & IFF_LINK0) && (sc->ep_connectors & BNC)) {
  647                 GO_WINDOW(0);
  648                 /* set the xcvr */
  649                 outw(BASE + EP_W0_ADDRESS_CFG, 3 << 14);
  650                 GO_WINDOW(2);
  651                 outw(BASE + EP_COMMAND, START_TRANSCEIVER);
  652                 GO_WINDOW(1);
  653         }
  654 #if defined(__NetBSD__) || defined(__FreeBSD__)
  655         if ((ifp->if_flags & IFF_LINK0) && (sc->ep_connectors & UTP)) {
  656 #else
  657         if ((ifp->if_flags & IFF_ALTPHYS) && (sc->ep_connectors & UTP)) {
  658 #endif
  659                 GO_WINDOW(4);
  660                 outw(BASE + EP_W4_MEDIA_TYPE, ENABLE_UTP);
  661                 GO_WINDOW(1);
  662         }
  663         outw(BASE + EP_COMMAND, RX_ENABLE);
  664         outw(BASE + EP_COMMAND, TX_ENABLE);
  665 
  666         ifp->if_flags |= IFF_RUNNING;
  667         ifp->if_flags &= ~IFF_OACTIVE;  /* just in case */
  668         sc->tx_start_thresh = 20;       /* probably a good starting point. */
  669         /* Store up a bunch of mbuf's for use later. (MAX_MBS). First we free
  670          * up any that we had in case we're being called from intr or
  671          * somewhere else. */
  672         sc->last_mb = 0;
  673         sc->next_mb = 0;
  674         zpmbuffill(sc);
  675         zpstart(ifp);
  676         splx(s);
  677 }
  678 
  679 static const char padmap[] = {0, 3, 2, 1};
  680 static void
  681 zpstart(ifp)
  682         struct ifnet *ifp;
  683 {
  684         register struct zp_softc *sc = ifp->if_softc;
  685         struct mbuf *m, *top;
  686 
  687         int     s, len, pad;
  688 
  689         s = splimp();
  690 
  691         if (sc->arpcom.ac_if.if_flags & IFF_OACTIVE) {
  692                 splx(s);
  693                 return;
  694         }
  695 startagain:
  696 
  697         /* Sneak a peek at the next packet */
  698         m = sc->arpcom.ac_if.if_snd.ifq_head;
  699         if (m == 0) {
  700                 splx(s);
  701                 return;
  702         }
  703         for (len = 0, top = m; m; m = m->m_next)
  704                 len += m->m_len;
  705 
  706         pad = padmap[len & 3];
  707 
  708         /* The 3c509 automatically pads short packets to minimum ethernet
  709          * length, but we drop packets that are too large. Perhaps we should
  710          * truncate them instead? */
  711         if (len + pad > ETHER_MAX_LEN) {
  712                 /* packet is obviously too large: toss it */
  713                 ++sc->arpcom.ac_if.if_oerrors;
  714                 IF_DEQUEUE(&sc->arpcom.ac_if.if_snd, m);
  715                 m_freem(m);
  716                 goto readcheck;
  717         }
  718         if (inw(BASE + EP_W1_FREE_TX) < len + pad + 4) {
  719                 /* no room in FIFO */
  720                 outw(BASE + EP_COMMAND, SET_TX_AVAIL_THRESH | (len + pad + 4));
  721                 sc->arpcom.ac_if.if_flags |= IFF_OACTIVE;
  722                 splx(s);
  723 
  724                 return;
  725         }
  726         IF_DEQUEUE(&sc->arpcom.ac_if.if_snd, m);
  727 
  728         if (m == 0) {           /* not really needed */
  729                 splx(s);
  730                 return;
  731         }
  732         outw(BASE + EP_COMMAND, SET_TX_START_THRESH |
  733             (len / 4 + sc->tx_start_thresh));
  734 
  735         outw(BASE + EP_W1_TX_PIO_WR_1, len);
  736         outw(BASE + EP_W1_TX_PIO_WR_1, 0xffff); /* Second dword meaningless */
  737 
  738         for (top = m; m != 0; m = m->m_next) {
  739                 if (sc->bus32bit) {
  740                         outsl(BASE + EP_W1_TX_PIO_WR_1, mtod(m, caddr_t),
  741                             m->m_len / 4);
  742                         if (m->m_len & 3)
  743                                 outsb(BASE + EP_W1_TX_PIO_WR_1,
  744                                     mtod(m, caddr_t) + (m->m_len & (~3)),
  745                                     m->m_len & 3);
  746                 } else {
  747                         outsw(BASE + EP_W1_TX_PIO_WR_1, mtod(m, caddr_t), m->m_len / 2);
  748                         if (m->m_len & 1)
  749                                 outb(BASE + EP_W1_TX_PIO_WR_1,
  750                                     *(mtod(m, caddr_t) + m->m_len - 1));
  751                 }
  752         }
  753         while (pad--)
  754                 outb(BASE + EP_W1_TX_PIO_WR_1, 0);      /* Padding */
  755 
  756 #if NBPFILTER > 0
  757         if (sc->arpcom.ac_if.if_bpf) {
  758                 bpf_mtap(&sc->arpcom.ac_if, top);
  759         }
  760 #endif
  761 
  762         m_freem(top);
  763         ++sc->arpcom.ac_if.if_opackets;
  764         /* Is another packet coming in? We don't want to overflow the tiny RX
  765          * fifo. */
  766 readcheck:
  767         if (inw(BASE + EP_W1_RX_STATUS) & RX_BYTES_MASK) {
  768                 splx(s);
  769                 return;
  770         }
  771         goto startagain;
  772 }
  773 void
  774 zpintr(unit)
  775         int     unit;
  776 {
  777         int     status, i;
  778         register struct zp_softc *sc = &zp_softc[unit];
  779 
  780         struct ifnet *ifp = &sc->arpcom.ac_if;
  781 
  782 
  783         status = 0;
  784 checkintr:
  785         status = inw(BASE + EP_STATUS) &
  786             (S_TX_COMPLETE | S_TX_AVAIL | S_RX_COMPLETE | S_CARD_FAILURE);
  787 checkintr2:
  788         if (status == 0) {
  789                 /* No interrupts. */
  790                 outw(BASE + EP_COMMAND, C_INTR_LATCH);
  791 
  792                 status = inw(BASE + EP_STATUS) &
  793                     (S_TX_COMPLETE | S_TX_AVAIL | S_RX_COMPLETE |
  794                         S_CARD_FAILURE);
  795                 if (status)
  796                         goto checkintr2;
  797 
  798                 return;
  799         }
  800         /* important that we do this first. */
  801         outw(BASE + EP_COMMAND, ACK_INTR | status);
  802 
  803         if (status & S_TX_AVAIL) {
  804                 status &= ~S_TX_AVAIL;
  805                 inw(BASE + EP_W1_FREE_TX);
  806                 sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
  807                 zpstart(&sc->arpcom.ac_if);
  808 
  809         }
  810         if (status & S_RX_COMPLETE) {
  811                 status &= ~S_RX_COMPLETE;
  812                 zpread(sc);
  813         }
  814         if (status & S_CARD_FAILURE) {
  815                 printf("zp%d: reset (status: %x)\n", unit, status);
  816                 outw(BASE + EP_COMMAND, C_INTR_LATCH);
  817                 zpinit(unit);
  818                 return;
  819         }
  820         if (status & S_TX_COMPLETE) {
  821                 status &= ~S_TX_COMPLETE;
  822                 /* We need to read TX_STATUS until we get a 0 status in order
  823                  * to turn off the interrupt flag. */
  824                 while ((i = inb(BASE + EP_W1_TX_STATUS)) & TXS_COMPLETE) {
  825                         outw(BASE + EP_W1_TX_STATUS, 0x0);
  826                         if (i & (TXS_MAX_COLLISION | TXS_JABBER | TXS_UNDERRUN)) {
  827                                 if (i & TXS_MAX_COLLISION)
  828                                         ++sc->arpcom.ac_if.if_collisions;
  829                                 if (i & (TXS_JABBER | TXS_UNDERRUN)) {
  830                                         outw(BASE + EP_COMMAND, TX_RESET);
  831                                         if (i & TXS_UNDERRUN) {
  832                                                 if (sc->tx_start_thresh < ETHER_MAX_LEN) {
  833                                                         sc->tx_start_thresh += 20;
  834                                                         outw(BASE + EP_COMMAND,
  835                                                             SET_TX_START_THRESH |
  836                                                             sc->tx_start_thresh);
  837                                                 }
  838                                         }
  839                                 }
  840                                 outw(BASE + EP_COMMAND, TX_ENABLE);
  841                                 ++sc->arpcom.ac_if.if_oerrors;
  842                         }
  843                 }
  844                 zpstart(ifp);
  845         }
  846         goto checkintr;
  847 }
  848 
  849 static void
  850 zpread(sc)
  851         register struct zp_softc *sc;
  852 {
  853         struct ether_header *eh;
  854         struct mbuf *mcur, *m, *m0, *top;
  855         int     totlen, lenthisone;
  856         int     save_totlen;
  857         int     off;
  858 
  859 
  860         totlen = inw(BASE + EP_W1_RX_STATUS);
  861         off = 0;
  862         top = 0;
  863 
  864         if (totlen & ERR_RX) {
  865                 ++sc->arpcom.ac_if.if_ierrors;
  866                 goto out;
  867         }
  868         save_totlen = totlen &= RX_BYTES_MASK;  /* Lower 11 bits = RX bytes. */
  869 
  870         m = sc->mb[sc->next_mb];
  871         sc->mb[sc->next_mb] = 0;
  872 
  873         if (m == 0) {
  874                 MGETHDR(m, M_DONTWAIT, MT_DATA);
  875                 if (m == 0)
  876                         goto out;
  877         } else {
  878                 /* Convert one of our saved mbuf's */
  879                 sc->next_mb = (sc->next_mb + 1) % MAX_MBS;
  880                 m->m_data = m->m_pktdat;
  881                 m->m_flags = M_PKTHDR;
  882         }
  883 
  884         top = m0 = m;           /* We assign top so we can "goto out" */
  885 #define EROUND  ((sizeof(struct ether_header) + 3) & ~3)
  886 #define EOFF    (EROUND - sizeof(struct ether_header))
  887         m0->m_data += EOFF;
  888         /* Read what should be the header. */
  889         insw(BASE + EP_W1_RX_PIO_RD_1,
  890             mtod(m0, caddr_t), sizeof(struct ether_header) / 2);
  891         m->m_len = sizeof(struct ether_header);
  892         totlen -= sizeof(struct ether_header);
  893         /* mostly deal with trailer here.  (untested) We do this in a couple
  894          * of parts.  First we check for a trailer, if we have one we convert
  895          * the mbuf back to a regular mbuf and set the offset and subtract
  896          * sizeof(struct ether_header) from the pktlen. After we've read the
  897          * packet off the interface (all except for the trailer header, we
  898          * then get a header mbuf, read the trailer into it, and fix up the
  899          * mbuf pointer chain. */
  900         eh = mtod(m, struct ether_header *);
  901         while (totlen > 0) {
  902                 lenthisone = min(totlen, M_TRAILINGSPACE(m));
  903                 if (lenthisone == 0) {  /* no room in this one */
  904                         mcur = m;
  905                         m = sc->mb[sc->next_mb];
  906                         sc->mb[sc->next_mb] = 0;
  907                         if (!m) {
  908                                 MGET(m, M_DONTWAIT, MT_DATA);
  909                                 if (m == 0)
  910                                         goto out;
  911                         } else {
  912                                 timeout(zpmbuffill, sc, 0);
  913                                 sc->next_mb = (sc->next_mb + 1) % MAX_MBS;
  914                         }
  915                         if (totlen >= MINCLSIZE)
  916                                 MCLGET(m, M_DONTWAIT);
  917                         m->m_len = 0;
  918                         mcur->m_next = m;
  919                         lenthisone = min(totlen, M_TRAILINGSPACE(m));
  920                 }
  921                 if (sc->bus32bit) {
  922                         insl(BASE + EP_W1_RX_PIO_RD_1, mtod(m, caddr_t) + m->m_len,
  923                             lenthisone / 4);
  924                         m->m_len += (lenthisone & ~3);
  925                         if (lenthisone & 3)
  926                                 insb(BASE + EP_W1_RX_PIO_RD_1,
  927                                     mtod(m, caddr_t) + m->m_len,
  928                                     lenthisone & 3);
  929                         m->m_len += (lenthisone & 3);
  930                 } else {
  931                         insw(BASE + EP_W1_RX_PIO_RD_1, mtod(m, caddr_t) + m->m_len,
  932                             lenthisone / 2);
  933                         m->m_len += lenthisone;
  934                         if (lenthisone & 1)
  935                                 *(mtod(m, caddr_t) + m->m_len - 1) = inb(BASE + EP_W1_RX_PIO_RD_1);
  936                 }
  937                 totlen -= lenthisone;
  938         }
  939         if (off) {
  940                 top = sc->mb[sc->next_mb];
  941                 sc->mb[sc->next_mb] = 0;
  942                 if (top == 0) {
  943                         MGETHDR(m, M_DONTWAIT, MT_DATA);
  944                         if (top == 0) {
  945                                 top = m0;
  946                                 goto out;
  947                         }
  948                 } else {
  949                         /* Convert one of our saved mbuf's */
  950                         sc->next_mb = (sc->next_mb + 1) % MAX_MBS;
  951                         top->m_data = top->m_pktdat;
  952                         top->m_flags = M_PKTHDR;
  953                 }
  954                 insw(BASE + EP_W1_RX_PIO_RD_1, mtod(top, caddr_t),
  955                     sizeof(struct ether_header));
  956                 top->m_next = m0;
  957                 top->m_len = sizeof(struct ether_header);
  958                 /* XXX Accomodate for type and len from beginning of trailer */
  959                 top->m_pkthdr.len = save_totlen - (2 * sizeof(u_short));
  960         } else {
  961                 top = m0;
  962                 top->m_pkthdr.len = save_totlen;
  963         }
  964 
  965         top->m_pkthdr.rcvif = &sc->arpcom.ac_if;
  966         outw(BASE + EP_COMMAND, RX_DISCARD_TOP_PACK);
  967         while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS);
  968         ++sc->arpcom.ac_if.if_ipackets;
  969 #if NBPFILTER > 0
  970         if (sc->arpcom.ac_if.if_bpf) {
  971                 bpf_mtap(&sc->arpcom.ac_if, top);
  972 
  973                 /* Note that the interface cannot be in promiscuous mode if
  974                  * there are no BPF listeners.  And if we are in promiscuous
  975                  * mode, we have to check if this packet is really ours. */
  976                 if ((sc->arpcom.ac_if.if_flags & IFF_PROMISC) &&
  977                     (eh->ether_dhost[0] & 1) == 0 &&
  978                     bcmp(eh->ether_dhost, sc->arpcom.ac_enaddr,
  979                         sizeof(eh->ether_dhost)) != 0 &&
  980                     bcmp(eh->ether_dhost, etherbroadcastaddr,
  981                         sizeof(eh->ether_dhost)) != 0) {
  982                         m_freem(top);
  983                         return;
  984                 }
  985         }
  986 #endif
  987         m_adj(top, sizeof(struct ether_header));
  988         ether_input(&sc->arpcom.ac_if, eh, top);
  989         return;
  990 
  991 out:    outw(BASE + EP_COMMAND, RX_DISCARD_TOP_PACK);
  992         while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS);
  993         if (top)
  994                 m_freem(top);
  995 
  996 }
  997 
  998 
  999 /*
 1000  * Look familiar?
 1001  */
 1002 static int
 1003 zpioctl(ifp, cmd, data)
 1004         register struct ifnet *ifp;
 1005         int     cmd;
 1006         caddr_t data;
 1007 {
 1008         register struct ifaddr *ifa = (struct ifaddr *) data;
 1009         struct zp_softc *sc = ifp->if_softc;
 1010         int     error = 0;
 1011 
 1012 
 1013         switch (cmd) {
 1014         case SIOCSIFADDR:
 1015                 ifp->if_flags |= IFF_UP;
 1016                 switch (ifa->ifa_addr->sa_family) {
 1017 #ifdef INET
 1018                 case AF_INET:
 1019                         zpinit(ifp->if_unit);   /* before arpwhohas */
 1020                         arp_ifinit((struct arpcom *) ifp, ifa);
 1021                         break;
 1022 #endif
 1023 #ifdef IPX
 1024                 case AF_IPX:
 1025                         {
 1026                                 register struct ipx_addr *ina = &(IA_SIPX(ifa)->sipx_addr);
 1027 
 1028                                 if (ipx_nullhost(*ina))
 1029                                         ina->x_host =
 1030                                             *(union ipx_host *) (sc->arpcom.ac_enaddr);
 1031                                 else {
 1032                                         ifp->if_flags &= ~IFF_RUNNING;
 1033                                         bcopy((caddr_t) ina->x_host.c_host,
 1034                                             (caddr_t) sc->arpcom.ac_enaddr,
 1035                                             sizeof(sc->arpcom.ac_enaddr));
 1036                                 }
 1037                                 zpinit(ifp->if_unit);
 1038                                 break;
 1039                         }
 1040 #endif
 1041 #ifdef NS
 1042                 case AF_NS:
 1043                         {
 1044                                 register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
 1045 
 1046                                 if (ns_nullhost(*ina))
 1047                                         ina->x_host =
 1048                                             *(union ns_host *) (sc->arpcom.ac_enaddr);
 1049                                 else {
 1050                                         ifp->if_flags &= ~IFF_RUNNING;
 1051                                         bcopy((caddr_t) ina->x_host.c_host,
 1052                                             (caddr_t) sc->arpcom.ac_enaddr,
 1053                                             sizeof(sc->arpcom.ac_enaddr));
 1054                                 }
 1055                                 zpinit(ifp->if_unit);
 1056                                 break;
 1057                         }
 1058 #endif
 1059                 default:
 1060                         zpinit(ifp->if_unit);
 1061                         break;
 1062                 }
 1063                 break;
 1064         case SIOCSIFFLAGS:
 1065                 if ((ifp->if_flags & IFF_UP) == 0 && ifp->if_flags & IFF_RUNNING) {
 1066                         ifp->if_flags &= ~IFF_RUNNING;
 1067                         zpstop(ifp->if_unit);
 1068                         zpmbufempty(sc);
 1069                         break;
 1070                 }
 1071                 zpinit(ifp->if_unit);
 1072                 break;
 1073         default:
 1074                 error = EINVAL;
 1075         }
 1076         return (error);
 1077 }
 1078 
 1079 static void
 1080 zpreset(unit)
 1081         int     unit;
 1082 {
 1083         int     s = splimp();
 1084 
 1085         zpstop(unit);
 1086         zpinit(unit);
 1087         splx(s);
 1088 }
 1089 
 1090 static void
 1091 zpwatchdog(ifp)
 1092         struct ifnet *ifp;
 1093 {
 1094         log(LOG_ERR, "zp%d: watchdog\n", ifp->if_unit);
 1095         ifp->if_oerrors++;
 1096         zpreset(ifp->if_unit);
 1097 }
 1098 
 1099 static void
 1100 zpstop(unit)
 1101         int     unit;
 1102 {
 1103         struct zp_softc *sc = &zp_softc[unit];
 1104 
 1105         outw(BASE + EP_COMMAND, RX_DISABLE);
 1106         outw(BASE + EP_COMMAND, RX_DISCARD_TOP_PACK);
 1107         while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS);
 1108         outw(BASE + EP_COMMAND, TX_DISABLE);
 1109         outw(BASE + EP_COMMAND, STOP_TRANSCEIVER);
 1110         outw(BASE + EP_COMMAND, RX_RESET);
 1111         outw(BASE + EP_COMMAND, TX_RESET);
 1112         outw(BASE + EP_COMMAND, C_INTR_LATCH);
 1113         outw(BASE + EP_COMMAND, SET_RD_0_MASK);
 1114         outw(BASE + EP_COMMAND, SET_INTR_MASK);
 1115         outw(BASE + EP_COMMAND, SET_RX_FILTER);
 1116 }
 1117 
 1118 
 1119 
 1120 static  u_short
 1121 read_eeprom_data(id_port, offset)
 1122         int     id_port;
 1123         int     offset;
 1124 {
 1125 
 1126         outb(id_port + 10, 0x80 + offset);
 1127         DELAY(1000);
 1128         return inw(id_port + 12);
 1129 }
 1130 
 1131 
 1132 
 1133 
 1134 static void
 1135 zpmbuffill(sp)
 1136         void   *sp;
 1137 {
 1138         struct zp_softc *sc = (struct zp_softc *) sp;
 1139         int     s, i;
 1140 
 1141         s = splimp();
 1142         i = sc->last_mb;
 1143         do {
 1144                 if (sc->mb[i] == NULL)
 1145                         MGET(sc->mb[i], M_DONTWAIT, MT_DATA);
 1146                 if (sc->mb[i] == NULL)
 1147                         break;
 1148                 i = (i + 1) % MAX_MBS;
 1149         } while (i != sc->next_mb);
 1150         sc->last_mb = i;
 1151         splx(s);
 1152 }
 1153 
 1154 static void
 1155 zpmbufempty(sc)
 1156         struct zp_softc *sc;
 1157 {
 1158         int     s, i;
 1159 
 1160         s = splimp();
 1161         for (i = 0; i < MAX_MBS; i++) {
 1162                 if (sc->mb[i]) {
 1163                         m_freem(sc->mb[i]);
 1164                         sc->mb[i] = NULL;
 1165                 }
 1166         }
 1167         sc->last_mb = sc->next_mb = 0;
 1168         untimeout(zpmbuffill, sc);
 1169         splx(s);
 1170 }

Cache object: be6e77b1ba49fef0a1a53fe7149178e8


[ 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.