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

Cache object: aec0d33f48b4dcf4015004252d94d296


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