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


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

FreeBSD/Linux Kernel Cross Reference
sys/dev/pcmcia/mhzc.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 /*      $NetBSD: mhzc.c,v 1.14 2003/01/01 00:10:23 thorpej Exp $        */
    2 
    3 /*-
    4  * Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
    9  * NASA Ames Research Center.
   10  *
   11  * Redistribution and use in source and binary forms, with or without
   12  * modification, are permitted provided that the following conditions
   13  * are met:
   14  * 1. Redistributions of source code must retain the above copyright
   15  *    notice, this list of conditions and the following disclaimer.
   16  * 2. Redistributions in binary form must reproduce the above copyright
   17  *    notice, this list of conditions and the following disclaimer in the
   18  *    documentation and/or other materials provided with the distribution.
   19  * 3. All advertising materials mentioning features or use of this software
   20  *    must display the following acknowledgement:
   21  *      This product includes software developed by the NetBSD
   22  *      Foundation, Inc. and its contributors.
   23  * 4. Neither the name of The NetBSD Foundation nor the names of its
   24  *    contributors may be used to endorse or promote products derived
   25  *    from this software without specific prior written permission.
   26  *
   27  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   28  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   29  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   30  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   31  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   37  * POSSIBILITY OF SUCH DAMAGE.
   38  */
   39 
   40 /*
   41  * Device driver for the Megaherz X-JACK Ethernet/Modem combo cards.
   42  *
   43  * Many thanks to Chuck Cranor for having the patience to sift through
   44  * the Linux smc91c92_cs.c driver to find the magic details to get this
   45  * working!
   46  */
   47 
   48 #include <sys/cdefs.h>
   49 __KERNEL_RCSID(0, "$NetBSD: mhzc.c,v 1.14 2003/01/01 00:10:23 thorpej Exp $");
   50 
   51 #include "opt_inet.h" 
   52 #include "opt_ns.h"
   53 #include "bpfilter.h"
   54 
   55 #include <sys/param.h>
   56 #include <sys/systm.h>
   57 #include <sys/mbuf.h>
   58 #include <sys/socket.h>
   59 #include <sys/ioctl.h>
   60 #include <sys/errno.h>
   61 #include <sys/syslog.h>
   62 #include <sys/select.h>
   63 #include <sys/tty.h>
   64 #include <sys/device.h>
   65 
   66 #include <net/if.h>     
   67 #include <net/if_dl.h>  
   68 #include <net/if_ether.h>
   69 #include <net/if_media.h> 
   70 
   71 #ifdef INET
   72 #include <netinet/in.h>
   73 #include <netinet/in_systm.h>
   74 #include <netinet/in_var.h>
   75 #include <netinet/ip.h>
   76 #include <netinet/if_inarp.h>
   77 #endif
   78         
   79 #ifdef NS 
   80 #include <netns/ns.h>
   81 #include <netns/ns_if.h>
   82 #endif  
   83 
   84 #if NBPFILTER > 0
   85 #include <net/bpf.h>
   86 #include <net/bpfdesc.h>
   87 #endif
   88 
   89 #include <machine/intr.h>
   90 #include <machine/bus.h>
   91 
   92 #include <dev/ic/comreg.h>
   93 #include <dev/ic/comvar.h>
   94 
   95 #include <dev/mii/mii.h>
   96 #include <dev/mii/miivar.h>
   97 
   98 #include <dev/ic/smc91cxxreg.h>
   99 #include <dev/ic/smc91cxxvar.h>
  100 
  101 #include <dev/pcmcia/pcmciareg.h>
  102 #include <dev/pcmcia/pcmciavar.h>
  103 #include <dev/pcmcia/pcmciadevs.h>
  104 
  105 #include "mhzc.h"
  106 
  107 struct mhzc_softc {
  108         struct device sc_dev;           /* generic device glue */
  109 
  110         struct pcmcia_function *sc_pf;  /* our PCMCIA function */
  111         void *sc_ih;                    /* interrupt handle */
  112 
  113         const struct mhzc_product *sc_product;
  114 
  115         /*
  116          * Data for the Modem portion.
  117          */
  118         struct device *sc_modem;
  119         struct pcmcia_io_handle sc_modem_pcioh;
  120         int sc_modem_io_window;
  121 
  122         /*
  123          * Data for the Ethernet portion.
  124          */
  125         struct device *sc_ethernet;
  126         struct pcmcia_io_handle sc_ethernet_pcioh;
  127         int sc_ethernet_io_window;
  128 
  129         int sc_flags;
  130 };
  131 
  132 /* sc_flags */
  133 #define MHZC_MODEM_MAPPED       0x01
  134 #define MHZC_ETHERNET_MAPPED    0x02
  135 #define MHZC_MODEM_ENABLED      0x04
  136 #define MHZC_ETHERNET_ENABLED   0x08
  137 #define MHZC_IOSPACE_ALLOCED    0x10
  138 
  139 int     mhzc_match __P((struct device *, struct cfdata *, void *));
  140 void    mhzc_attach __P((struct device *, struct device *, void *));
  141 int     mhzc_detach __P((struct device *, int));
  142 int     mhzc_activate __P((struct device *, enum devact));
  143 
  144 CFATTACH_DECL(mhzc, sizeof(struct mhzc_softc),
  145     mhzc_match, mhzc_attach, mhzc_detach, mhzc_activate);
  146 
  147 int     mhzc_em3336_enaddr __P((struct mhzc_softc *, u_int8_t *));
  148 int     mhzc_em3336_enable __P((struct mhzc_softc *));
  149 
  150 const struct mhzc_product {
  151         struct pcmcia_product mp_product;
  152 
  153         /* Get the Ethernet address for this card. */
  154         int             (*mp_enaddr) __P((struct mhzc_softc *, u_int8_t *));
  155 
  156         /* Perform any special `enable' magic. */
  157         int             (*mp_enable) __P((struct mhzc_softc *));
  158 } mhzc_products[] = {
  159         { { PCMCIA_STR_MEGAHERTZ_XJEM3336,      PCMCIA_VENDOR_MEGAHERTZ,
  160             PCMCIA_PRODUCT_MEGAHERTZ_XJEM3336,  0 },
  161           mhzc_em3336_enaddr,           mhzc_em3336_enable },
  162 
  163         /*
  164          * Eventually we could add support for other Ethernet/Modem
  165          * combo cards, even if they're aren't Megahertz, because
  166          * most of them work more or less the same way.
  167          */
  168 
  169         { { NULL } }
  170 };
  171 
  172 int     mhzc_print __P((void *, const char *));
  173 
  174 int     mhzc_check_cfe __P((struct mhzc_softc *, struct pcmcia_config_entry *));
  175 int     mhzc_alloc_ethernet __P((struct mhzc_softc *, struct pcmcia_config_entry *));
  176 
  177 int     mhzc_enable __P((struct mhzc_softc *, int));
  178 void    mhzc_disable __P((struct mhzc_softc *, int));
  179 
  180 int     mhzc_intr __P((void *));
  181 
  182 int
  183 mhzc_match(parent, match, aux)
  184         struct device *parent;
  185         struct cfdata *match;
  186         void *aux;
  187 {
  188         struct pcmcia_attach_args *pa = aux;
  189 
  190         if (pcmcia_product_lookup(pa,
  191             (const struct pcmcia_product *)mhzc_products,
  192             sizeof mhzc_products[0], NULL) != NULL)
  193                 return (10);            /* beat `com' */
  194 
  195         return (0);
  196 }
  197 
  198 void
  199 mhzc_attach(parent, self, aux)
  200         struct device *parent, *self;
  201         void *aux;
  202 {
  203         struct mhzc_softc *sc = (void *)self;
  204         struct pcmcia_attach_args *pa = aux;
  205         struct pcmcia_config_entry *cfe;
  206 
  207         sc->sc_pf = pa->pf;
  208 
  209         sc->sc_product = (const struct mhzc_product *)pcmcia_product_lookup(pa,
  210             (const struct pcmcia_product *)mhzc_products,
  211             sizeof mhzc_products[0], NULL);
  212         if (sc->sc_product == NULL) {
  213                 printf("\n");
  214                 panic("mhzc_attach: impossible");
  215         }
  216 
  217         printf(": %s\n", sc->sc_product->mp_product.pp_name);
  218 
  219         /*
  220          * The address decoders on these cards are wacky.  The configuration
  221          * entries are set up to look like serial ports, and have no
  222          * information about the Ethernet portion.  In order to talk to
  223          * the Modem portion, the I/O address must have bit 0x80 set.
  224          * In order to talk to the Ethernet portion, the I/O address must
  225          * have the 0x80 bit clear.
  226          *
  227          * The standard configuration entries conveniently have 0x80 set
  228          * in them, and have a length of 8 (a 16550's size, convenient!),
  229          * so we use those to set up the Modem portion.
  230          *
  231          * Once we have the Modem's address established, we search for
  232          * an address suitable for the Ethernet portion.  We do this by
  233          * rounding up to the next 16-byte aligned address where 0x80
  234          * isn't set (the SMC Ethernet chip has a 16-byte address size)
  235          * and attemping to allocate a 16-byte region until we succeed.
  236          *
  237          * Sure would have been nice if Megahertz had made the card a
  238          * proper multi-function device.
  239          */
  240         SIMPLEQ_FOREACH(cfe, &pa->pf->cfe_head, cfe_list) {
  241                 if (mhzc_check_cfe(sc, cfe)) {
  242                         /* Found one! */
  243                         break;
  244                 }
  245         }
  246         if (cfe == NULL) {
  247                 printf("%s: unable to find suitable config table entry\n",
  248                     sc->sc_dev.dv_xname);
  249                 return;
  250         }
  251 
  252         if (mhzc_alloc_ethernet(sc, cfe) == 0) {
  253                 printf("%s: unable to allocate space for Ethernet portion\n",
  254                     sc->sc_dev.dv_xname);
  255                 goto alloc_ethernet_failed;
  256         }
  257 
  258         /* Enable the card. */
  259         pcmcia_function_init(pa->pf, cfe);
  260         if (pcmcia_function_enable(pa->pf)) {
  261                 printf(": function enable failed\n");
  262                 goto enable_failed;
  263         }
  264         sc->sc_flags |= MHZC_IOSPACE_ALLOCED;
  265 
  266         if (sc->sc_product->mp_enable != NULL)
  267                 (*sc->sc_product->mp_enable)(sc);
  268 
  269         sc->sc_modem = config_found(&sc->sc_dev, "com", mhzc_print);
  270         sc->sc_ethernet = config_found(&sc->sc_dev, "sm", mhzc_print);
  271 
  272         pcmcia_function_disable(pa->pf);
  273         return;
  274 
  275  enable_failed:
  276         /* Free the Ethernet's I/O space. */
  277         pcmcia_io_free(sc->sc_pf, &sc->sc_ethernet_pcioh);
  278 
  279  alloc_ethernet_failed:
  280         /* Free the Modem's I/O space. */
  281         pcmcia_io_free(sc->sc_pf, &sc->sc_modem_pcioh);
  282 }
  283 
  284 int
  285 mhzc_check_cfe(sc, cfe)
  286         struct mhzc_softc *sc;
  287         struct pcmcia_config_entry *cfe;
  288 {
  289 
  290         if (cfe->num_memspace != 0)
  291                 return (0);
  292 
  293         if (cfe->num_iospace != 1)
  294                 return (0);
  295 
  296         if (pcmcia_io_alloc(sc->sc_pf,
  297             cfe->iospace[0].start,
  298             cfe->iospace[0].length,
  299             cfe->iospace[0].length,
  300             &sc->sc_modem_pcioh) == 0) {
  301                 /* Found one for the modem! */
  302                 return (1);
  303         }
  304 
  305         return (0);
  306 }
  307 
  308 int
  309 mhzc_alloc_ethernet(sc, cfe)
  310         struct mhzc_softc *sc;
  311         struct pcmcia_config_entry *cfe;
  312 {
  313         bus_addr_t addr, maxaddr;
  314 
  315         addr = cfe->iospace[0].start + cfe->iospace[0].length;
  316         maxaddr = 0x1000;
  317 
  318         /*
  319          * Now round it up so that it starts on a 16-byte boundary.
  320          */
  321         addr = roundup(addr, 0x10);
  322 
  323         for (; (addr + 0x10) < maxaddr; addr += 0x10) {
  324                 if (addr & 0x80)
  325                         continue;
  326                 if (pcmcia_io_alloc(sc->sc_pf, addr, 0x10, 0x10,
  327                     &sc->sc_ethernet_pcioh) == 0) {
  328                         /* Found one for the ethernet! */
  329                         return (1);
  330                 }
  331         }
  332 
  333         return (0);
  334 }
  335 
  336 int
  337 mhzc_print(aux, pnp)
  338         void *aux;
  339         const char *pnp;
  340 {
  341         const char *name = aux;
  342 
  343         if (pnp)
  344                 aprint_normal("%s at %s(*)",  name, pnp);
  345 
  346         return (UNCONF);
  347 }
  348 
  349 int
  350 mhzc_detach(self, flags)
  351         struct device *self;
  352         int flags;
  353 {
  354         struct mhzc_softc *sc = (void *)self;
  355         int rv;
  356 
  357         if (sc->sc_ethernet != NULL) {
  358                 rv = config_detach(sc->sc_ethernet, flags);
  359                 if (rv != 0)
  360                         return (rv);
  361                 sc->sc_ethernet = NULL;
  362         }
  363 
  364         if (sc->sc_modem != NULL) {
  365                 rv = config_detach(sc->sc_modem, flags);
  366                 if (rv != 0)
  367                         return (rv);
  368 #ifdef not_necessary
  369                 sc->sc_modem = NULL;
  370 #endif
  371         }
  372 
  373         /* Unmap our i/o windows. */
  374         if (sc->sc_flags & MHZC_MODEM_MAPPED)
  375                 pcmcia_io_unmap(sc->sc_pf, sc->sc_modem_io_window);
  376         if (sc->sc_flags & MHZC_ETHERNET_MAPPED)
  377                 pcmcia_io_unmap(sc->sc_pf, sc->sc_ethernet_io_window);
  378 
  379         /* Free our i/o spaces. */
  380         if (sc->sc_flags & MHZC_IOSPACE_ALLOCED) {
  381                 pcmcia_io_free(sc->sc_pf, &sc->sc_modem_pcioh);
  382                 pcmcia_io_free(sc->sc_pf, &sc->sc_ethernet_pcioh);
  383         }
  384 
  385         return (0);
  386 }
  387 
  388 int
  389 mhzc_activate(self, act)
  390         struct device *self;
  391         enum devact act;
  392 {
  393         struct mhzc_softc *sc = (void *)self;
  394         int s, rv = 0;
  395 
  396         s = splhigh();
  397         switch (act) {
  398         case DVACT_ACTIVATE:
  399                 rv = EOPNOTSUPP;
  400                 break;
  401 
  402         case DVACT_DEACTIVATE:
  403                 if (sc->sc_ethernet != NULL) {
  404                         rv = config_deactivate(sc->sc_ethernet);
  405                         if (rv != 0)
  406                                 goto out;
  407                 }
  408 
  409                 if (sc->sc_modem != NULL) {
  410                         rv = config_deactivate(sc->sc_modem);
  411                         if (rv != 0)
  412                                 goto out;
  413                 }
  414                 break;
  415         }
  416  out:
  417         splx(s);
  418         return (rv);
  419 }
  420 
  421 int
  422 mhzc_intr(arg)
  423         void *arg;
  424 {
  425         struct mhzc_softc *sc = arg;
  426         int rval = 0;
  427 
  428 #if NCOM_MHZC > 0
  429         if (sc->sc_modem != NULL &&
  430             (sc->sc_flags & MHZC_MODEM_ENABLED) != 0)
  431                 rval |= comintr(sc->sc_modem);
  432 #endif
  433 
  434 #if NSM_MHZC > 0
  435         if (sc->sc_ethernet != NULL &&
  436             (sc->sc_flags & MHZC_ETHERNET_ENABLED) != 0)
  437                 rval |= smc91cxx_intr(sc->sc_ethernet);
  438 #endif
  439 
  440         return (rval);
  441 }
  442 
  443 int
  444 mhzc_enable(sc, flag)
  445         struct mhzc_softc *sc;
  446         int flag;
  447 {
  448 
  449         if (sc->sc_flags & flag) {
  450                 printf("%s: %s already enabled\n", sc->sc_dev.dv_xname,
  451                     (flag & MHZC_MODEM_ENABLED) ? "modem" : "ethernet");
  452                 panic("mhzc_enable");
  453         }
  454 
  455         if ((sc->sc_flags & (MHZC_MODEM_ENABLED|MHZC_ETHERNET_ENABLED)) != 0) {
  456                 sc->sc_flags |= flag;
  457                 return (0);
  458         }
  459 
  460         /*
  461          * Establish our interrupt handler.
  462          *
  463          * XXX Note, we establish this at IPL_NET.  This is suboptimal
  464          * XXX the Modem portion, but is necessary to make the Ethernet
  465          * XXX portion have the correct interrupt level semantics.
  466          *
  467          * XXX Eventually we should use the `enabled' bits in the
  468          * XXX flags word to determine which level we should be at.
  469          */
  470         sc->sc_ih = pcmcia_intr_establish(sc->sc_pf, IPL_NET,
  471             mhzc_intr, sc);
  472         if (sc->sc_ih == NULL) {
  473                 printf("%s: unable to establish interrupt\n",
  474                     sc->sc_dev.dv_xname);
  475                 return (1);
  476         }
  477 
  478         if (pcmcia_function_enable(sc->sc_pf)) {
  479                 pcmcia_intr_disestablish(sc->sc_pf, sc->sc_ih);
  480                 return (1);
  481         }
  482 
  483         /*
  484          * Perform any special enable magic necessary.
  485          */
  486         if (sc->sc_product->mp_enable != NULL &&
  487             (*sc->sc_product->mp_enable)(sc) != 0) {
  488                 pcmcia_function_disable(sc->sc_pf);
  489                 pcmcia_intr_disestablish(sc->sc_pf, sc->sc_ih);
  490                 return (1);
  491         }
  492 
  493         sc->sc_flags |= flag;
  494         return (0);
  495 }
  496 
  497 void
  498 mhzc_disable(sc, flag)
  499         struct mhzc_softc *sc;
  500         int flag;
  501 {
  502 
  503         if ((sc->sc_flags & flag) == 0) {
  504                 printf("%s: %s already disabled\n", sc->sc_dev.dv_xname,
  505                     (flag & MHZC_MODEM_ENABLED) ? "modem" : "ethernet");
  506                 panic("mhzc_disable");
  507         }
  508 
  509         sc->sc_flags &= ~flag;
  510         if ((sc->sc_flags & (MHZC_MODEM_ENABLED|MHZC_ETHERNET_ENABLED)) != 0)
  511                 return;
  512 
  513         pcmcia_intr_disestablish(sc->sc_pf, sc->sc_ih);
  514         pcmcia_function_disable(sc->sc_pf);
  515 }
  516 
  517 /*****************************************************************************
  518  * Megahertz EM3336 (and compatibles) support
  519  *****************************************************************************/
  520 
  521 int     mhzc_em3336_lannid_ciscallback __P((struct pcmcia_tuple *, void *));
  522 int     mhzc_em3336_ascii_enaddr __P((const char *cisstr, u_int8_t *));
  523 
  524 int
  525 mhzc_em3336_enaddr(sc, myla)
  526         struct mhzc_softc *sc;
  527         u_int8_t *myla;
  528 {
  529 
  530         /* Get the station address from CIS tuple 0x81. */
  531         if (pcmcia_scan_cis(sc->sc_dev.dv_parent,
  532             mhzc_em3336_lannid_ciscallback, myla) != 1) {
  533                 printf("%s: unable to get Ethernet address from CIS\n",
  534                     sc->sc_dev.dv_xname);
  535                 return (0);
  536         }
  537 
  538         return (1);
  539 }
  540 
  541 int
  542 mhzc_em3336_enable(sc)
  543         struct mhzc_softc *sc;
  544 {
  545         struct pcmcia_mem_handle memh;
  546         bus_addr_t memoff;
  547         int memwin, reg;
  548 
  549         /*
  550          * Bring the chip to live by touching its registers in the correct
  551          * way (as per my reference... the Linux smc91c92_cs.c driver by
  552          * David A. Hinds).
  553          */
  554         
  555         /* Map the ISRPOWEREG. */
  556         if (pcmcia_mem_alloc(sc->sc_pf, 0x1000, &memh) != 0) {
  557                 printf("%s: unable to allocate memory space\n",
  558                     sc->sc_dev.dv_xname);
  559                 return (1);
  560         }
  561 
  562         if (pcmcia_mem_map(sc->sc_pf, PCMCIA_MEM_ATTR, 0, 0x1000,
  563             &memh, &memoff, &memwin)) {
  564                 printf("%s: unable to map memory space\n",
  565                     sc->sc_dev.dv_xname);
  566                 pcmcia_mem_free(sc->sc_pf, &memh);
  567                 return (1);
  568         }
  569 
  570         /*
  571          * The magic sequence:
  572          *
  573          *      - read/write the CCR option register.
  574          *      - read the ISRPOWEREG 2 times.
  575          *      - read/write the CCR option register again.
  576          */
  577 
  578         reg = pcmcia_ccr_read(sc->sc_pf, PCMCIA_CCR_OPTION);
  579         pcmcia_ccr_write(sc->sc_pf, PCMCIA_CCR_OPTION, reg);
  580 
  581         reg = bus_space_read_1(memh.memt, memh.memh, 0x380);
  582         delay(5);
  583         reg = bus_space_read_1(memh.memt, memh.memh, 0x380);
  584 
  585         delay(200000);
  586 
  587         reg = pcmcia_ccr_read(sc->sc_pf, PCMCIA_CCR_OPTION);
  588         delay(5);
  589         pcmcia_ccr_write(sc->sc_pf, PCMCIA_CCR_OPTION, reg);
  590 
  591         pcmcia_mem_unmap(sc->sc_pf, memwin);
  592         pcmcia_mem_free(sc->sc_pf, &memh);
  593 
  594         return (0);
  595 }
  596 
  597 int
  598 mhzc_em3336_lannid_ciscallback(tuple, arg)
  599         struct pcmcia_tuple *tuple;
  600         void *arg;
  601 {
  602         u_int8_t *myla = arg, addr_str[ETHER_ADDR_LEN * 2];
  603         int i;
  604 
  605         if (tuple->code == 0x81) {
  606                 /*
  607                  * We have a string-encoded address.  Length includes
  608                  * terminating 0xff.
  609                  */
  610                 if (tuple->length != (ETHER_ADDR_LEN * 2) + 1)
  611                         return (0);
  612 
  613                 for (i = 0; i < tuple->length - 1; i++)
  614                         addr_str[i] = pcmcia_tuple_read_1(tuple, i);
  615 
  616                 /*
  617                  * Decode the string into `myla'.
  618                  */
  619                 return (mhzc_em3336_ascii_enaddr(addr_str, myla));
  620         }
  621         return (0);
  622 }
  623 
  624 /* XXX This should be shared w/ if_sm_pcmcia.c */
  625 int
  626 mhzc_em3336_ascii_enaddr(cisstr, myla)
  627         const char *cisstr;
  628         u_int8_t *myla;
  629 {
  630         u_int8_t digit;
  631         int i;
  632 
  633         memset(myla, 0, ETHER_ADDR_LEN);
  634 
  635         for (i = 0, digit = 0; i < (ETHER_ADDR_LEN * 2); i++) {
  636                 if (cisstr[i] >= '' && cisstr[i] <= '9')
  637                         digit |= cisstr[i] - '';
  638                 else if (cisstr[i] >= 'a' && cisstr[i] <= 'f')
  639                         digit |= (cisstr[i] - 'a') + 10;
  640                 else if (cisstr[i] >= 'A' && cisstr[i] <= 'F')
  641                         digit |= (cisstr[i] - 'A') + 10;
  642                 else {
  643                         /* Bogus digit!! */
  644                         return (0);
  645                 }
  646 
  647                 /* Compensate for ordering of digits. */
  648                 if (i & 1) {
  649                         myla[i >> 1] = digit;
  650                         digit = 0;
  651                 } else
  652                         digit <<= 4;
  653         }
  654 
  655         return (1);
  656 }
  657 
  658 /****** Here begins the com attachment code. ******/
  659 
  660 #if NCOM_MHZC > 0
  661 int     com_mhzc_match __P((struct device *, struct cfdata *, void *));
  662 void    com_mhzc_attach __P((struct device *, struct device *, void *));
  663 int     com_mhzc_detach __P((struct device *, int));
  664 
  665 /* No mhzc-specific goo in the softc; it's all in the parent. */
  666 CFATTACH_DECL(com_mhzc, sizeof(struct com_softc),
  667     com_mhzc_match, com_mhzc_attach, com_detach, com_activate);
  668 
  669 int     com_mhzc_enable __P((struct com_softc *));
  670 void    com_mhzc_disable __P((struct com_softc *));
  671 
  672 int
  673 com_mhzc_match(parent, match, aux)
  674         struct device *parent;
  675         struct cfdata *match;
  676         void *aux;
  677 {
  678         extern struct cfdriver com_cd;
  679         const char *name = aux;
  680 
  681         /* Device is always present. */
  682         if (strcmp(name, com_cd.cd_name) == 0)
  683                 return (1);
  684 
  685         return (0);
  686 }
  687 
  688 void
  689 com_mhzc_attach(parent, self, aux)
  690         struct device *parent, *self;
  691         void *aux;
  692 {
  693         struct com_softc *sc = (void *)self;
  694         struct mhzc_softc *msc = (void *)parent;
  695 
  696         printf(":");
  697         if (pcmcia_io_map(msc->sc_pf, PCMCIA_WIDTH_IO8, 0,
  698             msc->sc_modem_pcioh.size, &msc->sc_modem_pcioh,
  699             &msc->sc_modem_io_window)) {
  700                 printf("unable to map I/O space\n");
  701                 return;
  702         }
  703         printf(" io 0x%x-0x%x",
  704             (int)msc->sc_modem_pcioh.addr,
  705             (int)(msc->sc_modem_pcioh.addr + msc->sc_modem_pcioh.size - 1));
  706 
  707         msc->sc_flags |= MHZC_MODEM_MAPPED;
  708 
  709         sc->sc_iot = msc->sc_modem_pcioh.iot;
  710         sc->sc_ioh = msc->sc_modem_pcioh.ioh;
  711 
  712         sc->enabled = 1;
  713 
  714         sc->sc_iobase = -1;
  715         sc->sc_frequency = COM_FREQ;
  716 
  717         sc->enable = com_mhzc_enable;
  718         sc->disable = com_mhzc_disable;
  719 
  720         com_attach_subr(sc);
  721 
  722         sc->enabled = 0;
  723 }
  724 
  725 int
  726 com_mhzc_enable(sc)
  727         struct com_softc *sc;
  728 {
  729 
  730         return (mhzc_enable((struct mhzc_softc *)sc->sc_dev.dv_parent,
  731             MHZC_MODEM_ENABLED));
  732 }
  733 
  734 void
  735 com_mhzc_disable(sc)
  736         struct com_softc *sc;
  737 {
  738 
  739         mhzc_disable((struct mhzc_softc *)sc->sc_dev.dv_parent,
  740             MHZC_MODEM_ENABLED);
  741 }
  742 
  743 #endif /* NCOM_MHZC > 0 */
  744 
  745 /****** Here begins the sm attachment code. ******/
  746 
  747 #if NSM_MHZC > 0
  748 int     sm_mhzc_match __P((struct device *, struct cfdata *, void *));
  749 void    sm_mhzc_attach __P((struct device *, struct device *, void *));
  750 
  751 /* No mhzc-specific goo in the softc; it's all in the parent. */
  752 CFATTACH_DECL(sm_mhzc, sizeof(struct smc91cxx_softc),
  753     sm_mhzc_match, sm_mhzc_attach, smc91cxx_detach, smc91cxx_activate);
  754 
  755 int     sm_mhzc_enable __P((struct smc91cxx_softc *));
  756 void    sm_mhzc_disable __P((struct smc91cxx_softc *));
  757 
  758 int
  759 sm_mhzc_match(parent, match, aux)
  760         struct device *parent;
  761         struct cfdata *match;
  762         void *aux;
  763 {
  764         extern struct cfdriver sm_cd;
  765         const char *name = aux;
  766 
  767         /* Device is always present. */
  768         if (strcmp(name, sm_cd.cd_name) == 0)
  769                 return (1);
  770 
  771         return (0);
  772 }
  773 
  774 void
  775 sm_mhzc_attach(parent, self, aux)
  776         struct device *parent, *self;
  777         void *aux;
  778 {
  779         struct smc91cxx_softc *sc = (void *)self;
  780         struct mhzc_softc *msc = (void *)parent;
  781         u_int8_t myla[ETHER_ADDR_LEN];
  782 
  783         printf(":");
  784         if (pcmcia_io_map(msc->sc_pf, PCMCIA_WIDTH_IO16, 0,
  785             msc->sc_ethernet_pcioh.size, &msc->sc_ethernet_pcioh,
  786             &msc->sc_ethernet_io_window)) {
  787                 printf("unable to map I/O space\n");
  788                 return;
  789         }
  790         printf(" io 0x%x-0x%x\n",
  791            (int)msc->sc_ethernet_pcioh.addr,
  792            (int)(msc->sc_ethernet_pcioh.addr + msc->sc_ethernet_pcioh.size - 1));
  793 
  794         msc->sc_flags |= MHZC_ETHERNET_MAPPED;
  795 
  796         sc->sc_bst = msc->sc_ethernet_pcioh.iot;
  797         sc->sc_bsh = msc->sc_ethernet_pcioh.ioh;
  798 
  799         sc->sc_enable = sm_mhzc_enable;
  800         sc->sc_disable = sm_mhzc_disable;
  801 
  802         if ((*msc->sc_product->mp_enaddr)(msc, myla) != 1)
  803                 return;
  804 
  805         /* Perform generic initialization. */
  806         smc91cxx_attach(sc, myla);
  807 }
  808 
  809 int
  810 sm_mhzc_enable(sc)
  811         struct smc91cxx_softc *sc;
  812 {
  813 
  814         return (mhzc_enable((struct mhzc_softc *)sc->sc_dev.dv_parent,
  815             MHZC_ETHERNET_ENABLED));
  816 }
  817 
  818 void
  819 sm_mhzc_disable(sc)
  820         struct smc91cxx_softc *sc;
  821 {
  822 
  823         mhzc_disable((struct mhzc_softc *)sc->sc_dev.dv_parent,
  824             MHZC_ETHERNET_ENABLED);
  825 }
  826 
  827 #endif /* NSM_MHZC > 0 */

Cache object: 6e1fb24c9595a2f0dff032a7b08f27d9


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