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/isic_pcmcia.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  * Copyright (c) 2002 The NetBSD Foundation, Inc.
    3  * All rights reserved.
    4  *
    5  * This code is derived from software contributed to The NetBSD Foundation
    6  * by Martin Husemann <martin@NetBSD.org>.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 3. All advertising materials mentioning features or use of this software
   17  *    must display the following acknowledgement:
   18  *        This product includes software developed by the NetBSD
   19  *        Foundation, Inc. and its contributors.
   20  * 4. Neither the name of The NetBSD Foundation nor the names of its
   21  *    contributors may be used to endorse or promote products derived
   22  *    from this software without specific prior written permission.
   23  *
   24  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   25  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   26  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   27  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   28  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   29  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   30  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   31  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   32  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   33  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   34  * POSSIBILITY OF SUCH DAMAGE.
   35  */
   36 
   37 #include <sys/cdefs.h>
   38 __KERNEL_RCSID(0, "$NetBSD: isic_pcmcia.c,v 1.23 2004/01/04 12:41:46 martin Exp $");
   39 
   40 #include <sys/param.h>
   41 #include <sys/errno.h>
   42 #include <sys/syslog.h>
   43 #include <sys/device.h>
   44 #include <sys/socket.h>
   45 #include <net/if.h>
   46 #include <sys/systm.h>
   47 #include <sys/malloc.h>
   48 
   49 #if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
   50 #include <sys/callout.h>
   51 #endif
   52 
   53 #include <machine/cpu.h>
   54 #include <machine/intr.h>
   55 #include <machine/bus.h>
   56 
   57 #include <dev/pcmcia/pcmciareg.h>
   58 #include <dev/pcmcia/pcmciavar.h>
   59 #include <dev/pcmcia/pcmciadevs.h>
   60 
   61 #ifdef __FreeBSD__
   62 #include <machine/i4b_ioctl.h>
   63 #include <machine/i4b_trace.h>
   64 #else
   65 #include <netisdn/i4b_ioctl.h>
   66 #include <netisdn/i4b_trace.h>
   67 #include <netisdn/i4b_debug.h>
   68 #include <netisdn/i4b_l2.h>
   69 #include <netisdn/i4b_l1l2.h>
   70 #endif
   71 
   72 #include <dev/ic/isic_l1.h>
   73 #include <dev/ic/ipac.h>
   74 #include <dev/ic/isac.h>
   75 #include <dev/ic/hscx.h>
   76 
   77 #include <netisdn/i4b_l1l2.h>
   78 #include <netisdn/i4b_global.h>
   79 
   80 #include <dev/pcmcia/isic_pcmcia.h>
   81 
   82 #include "opt_isicpcmcia.h"
   83 
   84 extern const struct isdn_layer1_isdnif_driver isic_std_driver;
   85 
   86 static int isic_pcmcia_match __P((struct device *, struct cfdata *, void *));
   87 static void isic_pcmcia_attach __P((struct device *, struct device *, void *));
   88 static const struct isic_pcmcia_card_entry * find_matching_card __P((struct pcmcia_attach_args *pa));
   89 static int isic_pcmcia_isdn_attach __P((struct isic_softc *sc, const char*));
   90 static int isic_pcmcia_detach(struct device *self, int flags);
   91 static int isic_pcmcia_activate(struct device *self, enum devact act);
   92 
   93 CFATTACH_DECL(isic_pcmcia, sizeof(struct pcmcia_isic_softc),
   94     isic_pcmcia_match, isic_pcmcia_attach,
   95     isic_pcmcia_detach, isic_pcmcia_activate);
   96 
   97 struct isic_pcmcia_card_entry {
   98         int32_t vendor;         /* vendor ID */
   99         int32_t product;        /* product ID */
  100         char *cis1_info[4];     /* CIS info to match */
  101         char *name;             /* name of controller */
  102         int function;           /* expected PCMCIA function type */
  103         int card_type;          /* card type found */
  104         isic_pcmcia_attach_func attach; /* card initialization */
  105 };
  106 
  107 static const struct isic_pcmcia_card_entry card_list[] = {
  108 
  109 #ifdef ISICPCMCIA_AVM_A1
  110     {   PCMCIA_VENDOR_INVALID, PCMCIA_PRODUCT_INVALID,
  111         { "AVM", "ISDN A", NULL, NULL },
  112         "AVM Fritz!Card", PCMCIA_FUNCTION_NETWORK,
  113         CARD_TYPEP_PCFRITZ, isic_attach_fritzpcmcia },
  114 #endif
  115 
  116 #ifdef ISICPCMCIA_ELSA_ISDNMC
  117     {   PCMCIA_VENDOR_INVALID, PCMCIA_PRODUCT_INVALID,
  118         { "ELSA GmbH, Aachen", "MicroLink ISDN/MC ", NULL, NULL },
  119         "ELSA MicroLink ISDN/MC", PCMCIA_FUNCTION_NETWORK,
  120         CARD_TYPEP_ELSAMLIMC, isic_attach_elsaisdnmc },
  121     {   PCMCIA_VENDOR_INVALID, PCMCIA_PRODUCT_INVALID,
  122         { "ELSA AG, Aachen", "MicroLink ISDN/MC ", NULL, NULL },
  123         "ELSA MicroLink ISDN/MC", PCMCIA_FUNCTION_NETWORK,
  124         CARD_TYPEP_ELSAMLIMC, isic_attach_elsaisdnmc },
  125     {   PCMCIA_VENDOR_INVALID, PCMCIA_PRODUCT_INVALID,
  126         { "ELSA AG (Aachen, Germany)", "MicroLink ISDN/MC ", NULL, NULL },
  127         "ELSA MicroLink ISDN/MC", PCMCIA_FUNCTION_NETWORK,
  128         CARD_TYPEP_ELSAMLIMC, isic_attach_elsaisdnmc },
  129 #endif
  130 
  131 #ifdef ISICPCMCIA_ELSA_MCALL
  132     {   0x105, 0x410a,
  133         { "ELSA", "MicroLink MC all", NULL, NULL },
  134         "ELSA MicroLink MCall", PCMCIA_FUNCTION_NETWORK,
  135         CARD_TYPEP_ELSAMLMCALL, isic_attach_elsamcall },
  136 #endif
  137 
  138 #ifdef ISICPCMCIA_SBSPEEDSTAR2
  139     {   0x020e, 0x0002,
  140         { "SEDLBAUER", "speed star II", NULL, NULL },
  141         "SEDLBAUER speed star II", PCMCIA_FUNCTION_NETWORK,
  142         CARD_TYPEP_SWS, isic_attach_sbspeedstar2 },
  143 #endif
  144 
  145 };
  146 #define NUM_MATCH_ENTRIES       (sizeof(card_list)/sizeof(card_list[0]))
  147 
  148 static const struct isic_pcmcia_card_entry *
  149 find_matching_card(pa)
  150         struct pcmcia_attach_args *pa;
  151 {
  152         int i, j;
  153 
  154         for (i = 0; i < NUM_MATCH_ENTRIES; i++) {
  155                 if (card_list[i].vendor != PCMCIA_VENDOR_INVALID && pa->card->manufacturer != card_list[i].vendor)
  156                         continue;
  157                 if (card_list[i].product != PCMCIA_PRODUCT_INVALID && pa->card->product != card_list[i].product)
  158                                 continue;
  159                 if (pa->pf->function != card_list[i].function)
  160                         continue;
  161                 for (j = 0; j < 4; j++) {
  162                         if (card_list[i].cis1_info[j] == NULL)
  163                                 continue;       /* wildcard */
  164                         if (pa->card->cis1_info[j] == NULL)
  165                                 break;          /* not available */
  166                         if (strcmp(pa->card->cis1_info[j], card_list[i].cis1_info[j]) != 0)
  167                                 break;          /* mismatch */
  168                 }
  169                 if (j >= 4)
  170                         break;
  171         }
  172         if (i >= NUM_MATCH_ENTRIES)
  173                 return NULL;
  174 
  175         return &card_list[i];
  176 }
  177 
  178 /*
  179  * Match card
  180  */
  181 static int
  182 isic_pcmcia_match(parent, match, aux)
  183         struct device *parent;
  184         struct cfdata *match;
  185         void *aux;
  186 {
  187         struct pcmcia_attach_args *pa = aux;
  188 
  189         if (!find_matching_card(pa))
  190                 return 0;
  191 
  192         return 1;
  193 }
  194 
  195 /*
  196  * Attach the card
  197  */
  198 static void
  199 isic_pcmcia_attach(parent, self, aux)
  200         struct device *parent, *self;
  201         void *aux;
  202 {
  203         struct pcmcia_isic_softc *psc = (void*) self;
  204         struct isic_softc *sc = &psc->sc_isic;
  205         struct pcmcia_attach_args *pa = aux;
  206         struct pcmcia_config_entry *cfe;
  207         const struct isic_pcmcia_card_entry * cde;
  208         int s;
  209 
  210         psc->sc_pf = pa->pf;
  211         cfe = SIMPLEQ_FIRST(&pa->pf->cfe_head);
  212         psc->sc_ih = NULL;
  213 
  214         /* Which card is it? */
  215         cde = find_matching_card(pa);
  216         if (cde == NULL) {
  217                 printf("%s: attach failed, couldn't find matching card\n",
  218                     psc->sc_isic.sc_dev.dv_xname);
  219                 return;
  220         }
  221         printf(": %s\n", cde->name);
  222 
  223         /* Enable the card */
  224         pcmcia_function_init(pa->pf, cfe);
  225         pcmcia_function_enable(pa->pf);
  226 
  227         if (!cde->attach(psc, cfe, pa)) {
  228                 pcmcia_function_disable(psc->sc_pf);
  229                 printf("%s: attach failed, card-specific attach unsuccesful\n",
  230                     psc->sc_isic.sc_dev.dv_xname);
  231                 return;
  232         }
  233 
  234         /* XXX - we generate interrupts during card initialization.
  235            Block them for now, until the handler is established. */
  236         s = splhigh();
  237 
  238         /* MI initilization */
  239         sc->sc_cardtyp = cde->card_type;
  240         if (isic_pcmcia_isdn_attach(sc, cde->name) == 0) {
  241                 /* setup interrupt */
  242                 psc->sc_ih = pcmcia_intr_establish(pa->pf, IPL_NET, isicintr, sc);
  243         } else {
  244                 pcmcia_function_disable(psc->sc_pf);
  245                 splx(s);
  246                 printf("%s: attach failed, couldn't establish interrupt\n",
  247                     psc->sc_isic.sc_dev.dv_xname);
  248                 return;
  249         }
  250 
  251         splx(s);
  252         return;
  253 }
  254 
  255 static int
  256 isic_pcmcia_detach(self, flags)
  257         struct device *self;
  258         int flags;
  259 {
  260         struct pcmcia_isic_softc *psc = (struct pcmcia_isic_softc *)self;
  261 
  262         pcmcia_function_disable(psc->sc_pf);
  263         pcmcia_io_unmap(psc->sc_pf, psc->sc_io_window);
  264         pcmcia_io_free(psc->sc_pf, &psc->sc_pcioh);
  265         if (psc->sc_ih != NULL)
  266                 pcmcia_intr_disestablish(psc->sc_pf, psc->sc_ih);
  267 
  268         return (0);
  269 }
  270 
  271 int
  272 isic_pcmcia_activate(self, act)
  273         struct device *self;
  274         enum devact act;
  275 {
  276         struct pcmcia_isic_softc *psc = (struct pcmcia_isic_softc *)self;
  277         int error = 0, s;
  278 
  279         s = splnet();
  280         switch (act) {
  281         case DVACT_ACTIVATE:
  282                 error = EOPNOTSUPP;
  283                 break;
  284 
  285         case DVACT_DEACTIVATE:
  286                 psc->sc_isic.sc_intr_valid = ISIC_INTR_DYING;
  287                 if (psc->sc_isic.sc_l3token != NULL)
  288                         isic_detach_bri(&psc->sc_isic);
  289                 break;
  290         }
  291         splx(s);
  292         return (error);
  293 }
  294         
  295 /*---------------------------------------------------------------------------*
  296  *      card independend attach for pcmicia cards
  297  *---------------------------------------------------------------------------*/
  298 
  299 /* parameter and format for message producing e.g. "isic0: " */
  300 
  301 #ifdef __FreeBSD__
  302 #define ISIC_FMT        "isic%d: "
  303 #define ISIC_PARM       dev->id_unit
  304 #define TERMFMT " "
  305 #else
  306 #define ISIC_FMT        "%s: "
  307 #define ISIC_PARM       sc->sc_dev.dv_xname
  308 #define TERMFMT "\n"
  309 #endif
  310 
  311 int
  312 isic_pcmcia_isdn_attach(struct isic_softc *sc, const char *cardname)
  313 {
  314         static char *ISACversion[] = {
  315                 "2085 Version A1/A2 or 2086/2186 Version 1.1",
  316                 "2085 Version B1",
  317                 "2085 Version B2",
  318                 "2085 Version V2.3 (B3)",
  319                 "Unknown Version"
  320         };
  321 
  322         static char *HSCXversion[] = {
  323                 "82525 Version A1",
  324                 "Unknown (0x01)",
  325                 "82525 Version A2",
  326                 "Unknown (0x03)",
  327                 "82525 Version A3",
  328                 "82525 or 21525 Version 2.1",
  329                 "Unknown Version"
  330         };
  331 
  332         sc->sc_l3token = NULL;
  333         sc->sc_isac_version = 0;
  334         sc->sc_isac_version = ((ISAC_READ(I_RBCH)) >> 5) & 0x03;
  335 
  336         switch(sc->sc_isac_version)
  337         {
  338                 case ISAC_VA:
  339                 case ISAC_VB1:
  340                 case ISAC_VB2:
  341                 case ISAC_VB3:
  342                         break;
  343 
  344                 default:
  345                         printf(ISIC_FMT "Error, ISAC version %d unknown!\n",
  346                                 ISIC_PARM, sc->sc_isac_version);
  347                         return(EIO);
  348         }
  349 
  350         sc->sc_hscx_version = HSCX_READ(0, H_VSTR) & 0xf;
  351 
  352         switch(sc->sc_hscx_version)
  353         {
  354                 case HSCX_VA1:
  355                 case HSCX_VA2:
  356                 case HSCX_VA3:
  357                 case HSCX_V21:
  358                         break;
  359 
  360                 default:
  361                         printf(ISIC_FMT "Error, HSCX version %d unknown!\n",
  362                                 ISIC_PARM, sc->sc_hscx_version);
  363                         return(EIO);
  364         };
  365 
  366         sc->sc_intr_valid = ISIC_INTR_DISABLED;
  367 
  368         /* HSCX setup */
  369 
  370         isic_bchannel_setup(sc, HSCX_CH_A, BPROT_NONE, 0);
  371         
  372         isic_bchannel_setup(sc, HSCX_CH_B, BPROT_NONE, 0);
  373 
  374         /* setup linktab */
  375 
  376         isic_init_linktab(sc);
  377 
  378         /* set trace level */
  379 
  380         sc->sc_trace = TRACE_OFF;
  381 
  382         sc->sc_state = ISAC_IDLE;
  383 
  384         sc->sc_ibuf = NULL;
  385         sc->sc_ib = NULL;
  386         sc->sc_ilen = 0;
  387 
  388         sc->sc_obuf = NULL;
  389         sc->sc_op = NULL;
  390         sc->sc_ol = 0;
  391         sc->sc_freeflag = 0;
  392 
  393         sc->sc_obuf2 = NULL;
  394         sc->sc_freeflag2 = 0;
  395 
  396 #if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
  397         callout_init(&sc->sc_T3_callout);
  398         callout_init(&sc->sc_T4_callout);
  399 #endif
  400 
  401         /* announce chip versions */
  402         
  403         if(sc->sc_isac_version >= ISAC_UNKN)
  404         {
  405                 printf(ISIC_FMT "ISAC Version UNKNOWN (VN=0x%x)" TERMFMT,
  406                                 ISIC_PARM,
  407                                 sc->sc_isac_version);
  408                 sc->sc_isac_version = ISAC_UNKN;
  409         }
  410         else
  411         {
  412                 printf(ISIC_FMT "ISAC %s (IOM-%c)" TERMFMT,
  413                                 ISIC_PARM,
  414                                 ISACversion[sc->sc_isac_version],
  415                                 sc->sc_bustyp == BUS_TYPE_IOM1 ? '1' : '2');
  416         }
  417 
  418         if(sc->sc_hscx_version >= HSCX_UNKN)
  419         {
  420                 printf(ISIC_FMT "HSCX Version UNKNOWN (VN=0x%x)" TERMFMT,
  421                                 ISIC_PARM,
  422                                 sc->sc_hscx_version);
  423                 sc->sc_hscx_version = HSCX_UNKN;
  424         }
  425         else
  426         {
  427                 printf(ISIC_FMT "HSCX %s" TERMFMT,
  428                                 ISIC_PARM,
  429                                 HSCXversion[sc->sc_hscx_version]);
  430         }
  431 
  432         /* init higher protocol layers */
  433         isic_attach_bri(sc, cardname, &isic_std_driver);
  434 
  435         return(0);
  436 }
  437 

Cache object: 0ca4edc62fed98b7db18033b78de5b34


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