LCOV - code coverage report
Current view: top level - dev/pcmcia - if_ep_pcmcia.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 123 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 7 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: if_ep_pcmcia.c,v 1.48 2015/11/25 11:20:38 mpi Exp $   */
       2             : /*      $NetBSD: if_ep_pcmcia.c,v 1.16 1998/08/17 23:20:40 thorpej Exp $  */
       3             : 
       4             : /*-
       5             :  * Copyright (c) 1998 The NetBSD Foundation, Inc.
       6             :  * All rights reserved.
       7             :  *
       8             :  * This code is derived from software contributed to The NetBSD Foundation
       9             :  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
      10             :  * NASA Ames Research Center.
      11             :  *
      12             :  * Redistribution and use in source and binary forms, with or without
      13             :  * modification, are permitted provided that the following conditions
      14             :  * are met:
      15             :  * 1. Redistributions of source code must retain the above copyright
      16             :  *    notice, this list of conditions and the following disclaimer.
      17             :  * 2. Redistributions in binary form must reproduce the above copyright
      18             :  *    notice, this list of conditions and the following disclaimer in the
      19             :  *    documentation and/or other materials provided with the distribution.
      20             :  *
      21             :  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
      22             :  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
      23             :  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
      24             :  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
      25             :  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      26             :  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
      27             :  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
      28             :  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
      29             :  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
      30             :  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      31             :  * POSSIBILITY OF SUCH DAMAGE.
      32             :  */
      33             : 
      34             : /*
      35             :  * Copyright (c) 1997 Marc Horowitz.  All rights reserved.
      36             :  *
      37             :  * Redistribution and use in source and binary forms, with or without
      38             :  * modification, are permitted provided that the following conditions
      39             :  * are met:
      40             :  * 1. Redistributions of source code must retain the above copyright
      41             :  *    notice, this list of conditions and the following disclaimer.
      42             :  * 2. Redistributions in binary form must reproduce the above copyright
      43             :  *    notice, this list of conditions and the following disclaimer in the
      44             :  *    documentation and/or other materials provided with the distribution.
      45             :  * 3. All advertising materials mentioning features or use of this software
      46             :  *    must display the following acknowledgement:
      47             :  *      This product includes software developed by Marc Horowitz.
      48             :  * 4. The name of the author may not be used to endorse or promote products
      49             :  *    derived from this software without specific prior written permission.
      50             :  *
      51             :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
      52             :  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
      53             :  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
      54             :  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
      55             :  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
      56             :  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      57             :  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      58             :  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      59             :  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
      60             :  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      61             :  */
      62             : 
      63             : #include "bpfilter.h"
      64             : 
      65             : #include <sys/param.h>
      66             : #include <sys/systm.h>
      67             : #include <sys/mbuf.h>
      68             : #include <sys/socket.h>
      69             : #include <sys/ioctl.h>
      70             : #include <sys/errno.h>
      71             : #include <sys/syslog.h>
      72             : #include <sys/selinfo.h>
      73             : #include <sys/timeout.h>
      74             : #include <sys/device.h>
      75             : 
      76             : #include <net/if.h>
      77             : #include <net/if_media.h>
      78             : 
      79             : #include <netinet/in.h>
      80             : #include <netinet/if_ether.h>
      81             : 
      82             : #if NBPFILTER > 0
      83             : #include <net/bpf.h>
      84             : #endif
      85             : 
      86             : #include <machine/cpu.h>
      87             : #include <machine/bus.h>
      88             : 
      89             : #include <dev/mii/mii.h>
      90             : #include <dev/mii/miivar.h>
      91             : 
      92             : #include <dev/ic/elink3var.h>
      93             : 
      94             : #include <dev/pcmcia/pcmciareg.h>
      95             : #include <dev/pcmcia/pcmciavar.h>
      96             : #include <dev/pcmcia/pcmciadevs.h>
      97             : 
      98             : int     ep_pcmcia_match(struct device *, void *, void *);
      99             : void    ep_pcmcia_attach(struct device *, struct device *, void *);
     100             : int     ep_pcmcia_detach(struct device *, int);
     101             : int     ep_pcmcia_activate(struct device *, int);
     102             : 
     103             : int     ep_pcmcia_get_enaddr(struct pcmcia_tuple *, void *);
     104             : #ifdef notyet
     105             : int     ep_pcmcia_enable(struct ep_softc *);
     106             : void    ep_pcmcia_disable(struct ep_softc *);
     107             : void    ep_pcmcia_disable1(struct ep_softc *);
     108             : #endif
     109             : 
     110             : int     ep_pcmcia_enable1(struct ep_softc *);
     111             : 
     112             : struct ep_pcmcia_softc {
     113             :         struct ep_softc sc_ep;                  /* real "ep" softc */
     114             : 
     115             :         /* PCMCIA-specific goo */
     116             :         struct pcmcia_io_handle sc_pcioh;       /* PCMCIA i/o space info */
     117             :         int sc_io_window;                       /* our i/o window */
     118             :         struct pcmcia_function *sc_pf;          /* our PCMCIA function */
     119             : };
     120             : 
     121             : struct cfattach ep_pcmcia_ca = {
     122             :         sizeof(struct ep_pcmcia_softc), ep_pcmcia_match, ep_pcmcia_attach,
     123             :         ep_pcmcia_detach, ep_pcmcia_activate
     124             : };
     125             : 
     126             : struct ep_pcmcia_product {
     127             :         u_int16_t       epp_product;    /* PCMCIA product ID */
     128             :         u_short         epp_chipset;    /* 3Com chipset used */
     129             :         int             epp_flags;      /* initial softc flags */
     130             :         int             epp_expfunc;    /* expected function */
     131             : } ep_pcmcia_prod[] = {
     132             :         { PCMCIA_PRODUCT_3COM_3C562,    EP_CHIPSET_3C509,
     133             :           0,                            0 },
     134             : 
     135             :         { PCMCIA_PRODUCT_3COM_3C589,    EP_CHIPSET_3C509,
     136             :           0,                            0 },
     137             : 
     138             :         { PCMCIA_PRODUCT_3COM_3CXEM556, EP_CHIPSET_3C509,
     139             :           0,                            0 },
     140             : 
     141             :         { PCMCIA_PRODUCT_3COM_3CXEM556B,EP_CHIPSET_3C509,
     142             :           0,                            0 },
     143             : 
     144             :         { PCMCIA_PRODUCT_3COM_3C1,      EP_CHIPSET_3C509,
     145             :           0,                            0 },
     146             : 
     147             :         { PCMCIA_PRODUCT_3COM_3CCFEM556BI, EP_CHIPSET_ROADRUNNER,
     148             :           EP_FLAGS_MII,                 0 },
     149             : 
     150             :         { PCMCIA_PRODUCT_3COM_3C574,    EP_CHIPSET_ROADRUNNER,
     151             :           EP_FLAGS_MII,                 0 }
     152             : };
     153             : 
     154             : struct ep_pcmcia_product *ep_pcmcia_lookup(struct pcmcia_attach_args *);
     155             : 
     156             : struct ep_pcmcia_product *
     157           0 : ep_pcmcia_lookup(pa)
     158             :         struct pcmcia_attach_args *pa;
     159             : {
     160             :         int i;
     161             : 
     162           0 :         for (i = 0; i < nitems(ep_pcmcia_prod); i++)
     163           0 :                 if (pa->product == ep_pcmcia_prod[i].epp_product &&
     164           0 :                     pa->pf->number == ep_pcmcia_prod[i].epp_expfunc)
     165           0 :                         return &ep_pcmcia_prod[i];
     166             : 
     167           0 :         return (NULL);
     168           0 : }
     169             : 
     170             : int
     171           0 : ep_pcmcia_match(parent, match, aux)
     172             :         struct device *parent;
     173             :         void *match, *aux;
     174             : {
     175           0 :         struct pcmcia_attach_args *pa = aux;
     176             : 
     177           0 :         if (pa->manufacturer != PCMCIA_VENDOR_3COM)
     178           0 :                 return (0);
     179             : 
     180           0 :         if (ep_pcmcia_lookup(pa) != NULL)
     181           0 :                 return (1);
     182             : 
     183           0 :         return (0);
     184           0 : }
     185             : 
     186             : #ifdef notdef
     187             : int
     188             : ep_pcmcia_enable(sc)
     189             :         struct ep_softc *sc;
     190             : {
     191             :         struct ep_pcmcia_softc *psc = (struct ep_pcmcia_softc *) sc;
     192             :         struct pcmcia_function *pf = psc->sc_pf;
     193             : 
     194             :         /* establish the interrupt. */
     195             :         sc->sc_ih = pcmcia_intr_establish(pf, IPL_NET, epintr,
     196             :             sc, sc->sc_dev.dv_xname);
     197             :         if (sc->sc_ih == NULL) {
     198             :                 printf("%s: couldn't establish interrupt\n",
     199             :                     sc->sc_dev.dv_xname);
     200             :                 return (1);
     201             :         }
     202             : 
     203             :         return (ep_pcmcia_enable1(sc));
     204             : }
     205             : #endif
     206             : 
     207             : int
     208           0 : ep_pcmcia_enable1(sc)
     209             :         struct ep_softc *sc;
     210             : {
     211           0 :         struct ep_pcmcia_softc *psc = (struct ep_pcmcia_softc *) sc;
     212           0 :         struct pcmcia_function *pf = psc->sc_pf;
     213             :         int ret;
     214             : 
     215           0 :         if ((ret = pcmcia_function_enable(pf)))
     216           0 :                 return (ret);
     217             : 
     218           0 :         if ((psc->sc_pf->sc->card.product == PCMCIA_PRODUCT_3COM_3C562) ||
     219           0 :             (psc->sc_pf->sc->card.product == PCMCIA_PRODUCT_3COM_3CXEM556) ||
     220           0 :             (psc->sc_pf->sc->card.product == PCMCIA_PRODUCT_3COM_3CXEM556B)) {
     221             :                 int reg;
     222             : 
     223             :                 /* turn off the serial-disable bit */
     224             : 
     225           0 :                 reg = pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION);
     226           0 :                 if (reg & 0x08) {
     227           0 :                         reg &= ~0x08;
     228           0 :                         pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
     229           0 :                 }
     230             : 
     231           0 :         }
     232             : 
     233           0 :         return (ret);
     234           0 : }
     235             : 
     236             : #ifdef notyet
     237             : void
     238             : ep_pcmcia_disable(sc)
     239             :         struct ep_softc *sc;
     240             : {
     241             :         struct ep_pcmcia_softc *psc = (struct ep_pcmcia_softc *) sc;
     242             : 
     243             :         pcmcia_intr_disestablish(psc->sc_pf, sc->sc_ih);
     244             :         ep_pcmcia_disable1(sc);
     245             : }
     246             : 
     247             : void
     248             : ep_pcmcia_disable1(sc)
     249             :         struct ep_softc *sc;
     250             : {
     251             :         struct ep_pcmcia_softc *psc = (struct ep_pcmcia_softc *) sc;
     252             : 
     253             :         pcmcia_function_disable(psc->sc_pf);
     254             : }
     255             : #endif
     256             : 
     257             : void
     258           0 : ep_pcmcia_attach(parent, self, aux)
     259             :         struct device  *parent, *self;
     260             :         void           *aux;
     261             : {
     262           0 :         struct ep_pcmcia_softc *psc = (void *) self;
     263           0 :         struct ep_softc *sc = &psc->sc_ep;
     264           0 :         struct pcmcia_attach_args *pa = aux;
     265             :         struct pcmcia_config_entry *cfe;
     266             :         struct ep_pcmcia_product *epp;
     267           0 :         u_int8_t myla[ETHER_ADDR_LEN];
     268             :         u_int8_t *enaddr = NULL;
     269             :         const char *intrstr;
     270             :         int i;
     271             : 
     272           0 :         psc->sc_pf = pa->pf;
     273           0 :         cfe = SIMPLEQ_FIRST(&pa->pf->cfe_head);
     274             : 
     275             :         /* Enable the card. */
     276           0 :         pcmcia_function_init(pa->pf, cfe);
     277           0 :         if (ep_pcmcia_enable1(sc))
     278           0 :                 printf(": function enable failed\n");
     279             : 
     280             : #ifdef notyet
     281             :         sc->enabled = 1;
     282             : #endif
     283             : 
     284           0 :         if (cfe->num_memspace != 0)
     285           0 :                 printf(": unexpected number of memory spaces %d should be 0\n",
     286             :                     cfe->num_memspace);
     287             : 
     288           0 :         if (cfe->num_iospace != 1)
     289           0 :                 printf(": unexpected number of I/O spaces %d should be 1\n",
     290             :                     cfe->num_iospace);
     291             : 
     292           0 :         if (pa->product == PCMCIA_PRODUCT_3COM_3C562) {
     293           0 :                 bus_addr_t maxaddr = (pa->pf->sc->iobase + pa->pf->sc->iosize);
     294             : 
     295           0 :                 for (i = pa->pf->sc->iobase; i < maxaddr; i += 0x10) {
     296             :                         /*
     297             :                          * the 3c562 can only use 0x??00-0x??7f
     298             :                          * according to the Linux driver
     299             :                          */
     300           0 :                         if (i & 0x80)
     301             :                                 continue;
     302           0 :                         if (pcmcia_io_alloc(pa->pf, i, cfe->iospace[0].length,
     303           0 :                             cfe->iospace[0].length, &psc->sc_pcioh) == 0)
     304             :                                 break;
     305             :                 }
     306           0 :                 if (i >= maxaddr) {
     307           0 :                         printf(": can't allocate i/o space\n");
     308           0 :                         return;
     309             :                 }
     310           0 :         } else {
     311           0 :                 if (pcmcia_io_alloc(pa->pf, 0, cfe->iospace[0].length,
     312             :                     cfe->iospace[0].length, &psc->sc_pcioh))
     313           0 :                         printf(": can't allocate i/o space\n");
     314             :         }
     315             : 
     316           0 :         sc->sc_iot = psc->sc_pcioh.iot;
     317           0 :         sc->sc_ioh = psc->sc_pcioh.ioh;
     318             : 
     319           0 :         if (pcmcia_io_map(pa->pf, ((cfe->flags & PCMCIA_CFE_IO16) ?
     320           0 :             PCMCIA_WIDTH_IO16 : PCMCIA_WIDTH_IO8), 0, cfe->iospace[0].length,
     321           0 :             &psc->sc_pcioh, &psc->sc_io_window)) {
     322           0 :                 printf(": can't map i/o space\n");
     323           0 :                 return;
     324             :         }
     325             : 
     326           0 :         printf(" port 0x%lx/%ld", psc->sc_pcioh.addr, psc->sc_pcioh.size);
     327             : 
     328           0 :         switch (pa->product) {
     329             :         case PCMCIA_PRODUCT_3COM_3C562:
     330             :                 /*
     331             :                  * 3c562a-c use this; 3c562d does it in the regular way.
     332             :                  * we might want to check the revision and produce a warning
     333             :                  * in the future.
     334             :                  */
     335             :                 /* FALLTHROUGH */
     336             :         case PCMCIA_PRODUCT_3COM_3C574:
     337             :         case PCMCIA_PRODUCT_3COM_3CCFEM556BI:
     338             :                 /*
     339             :                  * Apparently, some 3c574s do it this way, as well.
     340             :                  */
     341           0 :                 if (pcmcia_scan_cis(parent, ep_pcmcia_get_enaddr, myla))
     342           0 :                         enaddr = myla;
     343             :                 break;
     344             :         }
     345             : 
     346           0 :         sc->bustype = EP_BUS_PCMCIA;
     347             : 
     348           0 :         epp = ep_pcmcia_lookup(pa);
     349           0 :         if (epp == NULL)
     350           0 :                 panic("ep_pcmcia_attach: impossible");
     351             : 
     352           0 :         sc->ep_flags = epp->epp_flags;
     353             : 
     354             : #ifdef notyet
     355             :         sc->enable = ep_pcmcia_enable;
     356             :         sc->disable = ep_pcmcia_disable;
     357             : #endif
     358             : 
     359             :         /* establish the interrupt. */
     360           0 :         sc->sc_ih = pcmcia_intr_establish(pa->pf, IPL_NET, epintr, sc,
     361           0 :             sc->sc_dev.dv_xname);
     362           0 :         intrstr = pcmcia_intr_string(psc->sc_pf, sc->sc_ih);
     363           0 :         if (*intrstr)
     364           0 :                 printf(", %s", intrstr);
     365             : 
     366           0 :         printf(":");
     367             : 
     368           0 :         epconfig(sc, epp->epp_chipset, enaddr);
     369             : 
     370             : #ifdef notyet
     371             :         sc->enabled = 0;
     372             : 
     373             :         ep_pcmcia_disable1(sc);
     374             : #endif
     375           0 : }
     376             : 
     377             : int
     378           0 : ep_pcmcia_detach(dev, flags)
     379             :         struct device *dev;
     380             :         int flags;
     381             : {
     382             :         int rv;
     383           0 :         struct ep_pcmcia_softc *psc = (struct ep_pcmcia_softc *)dev;
     384             : 
     385           0 :         if ((rv = ep_detach(dev)) != 0)
     386           0 :                 return (rv);
     387             : 
     388           0 :         pcmcia_io_unmap(psc->sc_pf, psc->sc_io_window);
     389           0 :         pcmcia_io_free(psc->sc_pf, &psc->sc_pcioh);
     390             : 
     391           0 :         return (0);
     392           0 : }
     393             : 
     394             : int
     395           0 : ep_pcmcia_activate(dev, act)
     396             :         struct device *dev;
     397             :         int act;
     398             : {
     399           0 :         struct ep_pcmcia_softc *sc = (struct ep_pcmcia_softc *)dev;
     400           0 :         struct ep_softc *esc = &sc->sc_ep;
     401           0 :         struct ifnet *ifp = &esc->sc_arpcom.ac_if;
     402             : 
     403           0 :         switch (act) {
     404             :         case DVACT_SUSPEND:
     405           0 :                 ifp->if_timer = 0;
     406           0 :                 if (ifp->if_flags & IFF_RUNNING)
     407           0 :                         epstop(esc);
     408           0 :                 if (sc->sc_ep.sc_ih)
     409           0 :                         pcmcia_intr_disestablish(sc->sc_pf, sc->sc_ep.sc_ih);
     410           0 :                 sc->sc_ep.sc_ih = NULL;
     411           0 :                 pcmcia_function_disable(sc->sc_pf);
     412           0 :                 break;
     413             :         case DVACT_RESUME:
     414           0 :                 pcmcia_function_enable(sc->sc_pf);
     415           0 :                 sc->sc_ep.sc_ih = pcmcia_intr_establish(sc->sc_pf, IPL_NET,
     416           0 :                     epintr, sc, esc->sc_dev.dv_xname);
     417           0 :                 if (ifp->if_flags & IFF_UP)
     418           0 :                         epinit(esc);
     419             :                 break;
     420             :         case DVACT_DEACTIVATE:
     421           0 :                 if (sc->sc_ep.sc_ih)
     422           0 :                         pcmcia_intr_disestablish(sc->sc_pf, sc->sc_ep.sc_ih);
     423           0 :                 sc->sc_ep.sc_ih = NULL;
     424           0 :                 pcmcia_function_disable(sc->sc_pf);
     425           0 :                 break;
     426             :         }
     427           0 :         return (0);
     428             : }
     429             : 
     430             : int
     431           0 : ep_pcmcia_get_enaddr(tuple, arg)
     432             :         struct pcmcia_tuple *tuple;
     433             :         void *arg;
     434             : {
     435             :         u_int8_t *myla = arg;
     436             :         int i;
     437             : 
     438             :         /* this is 3c562a-c magic */
     439           0 :         if (tuple->code == 0x88) {
     440           0 :                 if (tuple->length < ETHER_ADDR_LEN)
     441           0 :                         return (0);
     442             : 
     443           0 :                 for (i = 0; i < ETHER_ADDR_LEN; i += 2) {
     444           0 :                         myla[i] = pcmcia_tuple_read_1(tuple, i + 1);
     445           0 :                         myla[i + 1] = pcmcia_tuple_read_1(tuple, i);
     446             :                 }
     447             : 
     448           0 :                 return (1);
     449             :         }
     450           0 :         return (0);
     451           0 : }

Generated by: LCOV version 1.13