root/dev/pcmcia/com_pcmcia.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. com_pcmcia_match
  2. com_pcmcia_activate
  3. com_pcmcia_attach
  4. com_pcmcia_detach
  5. com_pcmcia_enable
  6. com_pcmcia_enable1
  7. com_pcmcia_disable
  8. com_pcmcia_disable1

    1 /*      $OpenBSD: com_pcmcia.c,v 1.46 2006/05/28 16:49:46 fkr Exp $     */
    2 /*      $NetBSD: com_pcmcia.c,v 1.15 1998/08/22 17:47:58 msaitoh Exp $  */
    3 
    4 /*
    5  * Copyright (c) 1997 - 1999, Jason Downs.  All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. Neither the name(s) of the author(s) nor the name OpenBSD
   16  *    may be used to endorse or promote products derived from this software
   17  *    without specific prior written permission.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS
   20  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   22  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT,
   23  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
   25  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
   26  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   29  * SUCH DAMAGE.
   30  */
   31 /*-
   32  * Copyright (c) 1998 The NetBSD Foundation, Inc.
   33  * All rights reserved.
   34  *
   35  * This code is derived from software contributed to The NetBSD Foundation
   36  * by Charles M. Hannum.
   37  *
   38  * Redistribution and use in source and binary forms, with or without
   39  * modification, are permitted provided that the following conditions
   40  * are met:
   41  * 1. Redistributions of source code must retain the above copyright
   42  *    notice, this list of conditions and the following disclaimer.
   43  * 2. Redistributions in binary form must reproduce the above copyright
   44  *    notice, this list of conditions and the following disclaimer in the
   45  *    documentation and/or other materials provided with the distribution.
   46  * 3. All advertising materials mentioning features or use of this software
   47  *    must display the following acknowledgement:
   48  *        This product includes software developed by the NetBSD
   49  *        Foundation, Inc. and its contributors.
   50  * 4. Neither the name of The NetBSD Foundation nor the names of its
   51  *    contributors may be used to endorse or promote products derived
   52  *    from this software without specific prior written permission.
   53  *
   54  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   55  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   56  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   57  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   58  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   59  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   60  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   61  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   62  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   63  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   64  * POSSIBILITY OF SUCH DAMAGE.
   65  */
   66 
   67 /*-
   68  * Copyright (c) 1991 The Regents of the University of California.
   69  * All rights reserved.
   70  *
   71  * Redistribution and use in source and binary forms, with or without
   72  * modification, are permitted provided that the following conditions
   73  * are met:
   74  * 1. Redistributions of source code must retain the above copyright
   75  *    notice, this list of conditions and the following disclaimer.
   76  * 2. Redistributions in binary form must reproduce the above copyright
   77  *    notice, this list of conditions and the following disclaimer in the
   78  *    documentation and/or other materials provided with the distribution.
   79  * 3. Neither the name of the University nor the names of its contributors
   80  *    may be used to endorse or promote products derived from this software
   81  *    without specific prior written permission.
   82  *
   83  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   84  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   85  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   86  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   87  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   88  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   89  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   90  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   91  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   92  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   93  * SUCH DAMAGE.
   94  *
   95  *      @(#)com.c       7.5 (Berkeley) 5/16/91
   96  */
   97 
   98 #include <sys/param.h>
   99 #include <sys/systm.h>
  100 #include <sys/ioctl.h>
  101 #include <sys/selinfo.h>
  102 #include <sys/tty.h>
  103 #include <sys/proc.h>
  104 #include <sys/user.h>
  105 #include <sys/conf.h>
  106 #include <sys/file.h>
  107 #include <sys/uio.h>
  108 #include <sys/kernel.h>
  109 #include <sys/syslog.h>
  110 #include <sys/types.h>
  111 #include <sys/device.h>
  112 
  113 #include <machine/intr.h>
  114 #include <machine/bus.h>
  115 
  116 #include <dev/pcmcia/pcmciavar.h>
  117 #include <dev/pcmcia/pcmciareg.h>
  118 #include <dev/pcmcia/pcmciadevs.h>
  119 
  120 #include "com.h"
  121 #ifdef i386
  122 #include "pccom.h"
  123 #endif
  124 
  125 #include <dev/ic/comreg.h>
  126 #if NPCCOM > 0
  127 #include <i386/isa/pccomvar.h>
  128 #endif
  129 #if NCOM > 0
  130 #include <dev/ic/comvar.h>
  131 #endif
  132 #include <dev/ic/ns16550reg.h>
  133 
  134 #include <dev/isa/isareg.h>
  135 
  136 #define com_lcr         com_cfcr
  137 
  138 /* Devices that we need to match by CIS strings */
  139 struct com_pcmcia_product {
  140         char *cis1_info[4];
  141 } com_pcmcia_prod[] = {
  142         { PCMCIA_CIS_MEGAHERTZ_XJ2288 },
  143         { PCMCIA_CIS_NOVATEL_NRM6831 },
  144 };
  145 
  146 int com_pcmcia_match(struct device *, void *, void *);
  147 void com_pcmcia_attach(struct device *, struct device *, void *);
  148 int com_pcmcia_detach(struct device *, int);
  149 void com_pcmcia_cleanup(void *);
  150 int com_pcmcia_activate(struct device *, enum devact);
  151 
  152 int com_pcmcia_enable(struct com_softc *);
  153 void com_pcmcia_disable(struct com_softc *);
  154 int com_pcmcia_enable1(struct com_softc *);
  155 void com_pcmcia_disable1(struct com_softc *);
  156 
  157 struct com_pcmcia_softc {
  158         struct com_softc sc_com;                /* real "com" softc */
  159 
  160         /* PCMCIA-specific goo */
  161         struct pcmcia_io_handle sc_pcioh;       /* PCMCIA i/o space info */
  162         int sc_io_window;                       /* our i/o window */
  163         struct pcmcia_function *sc_pf;          /* our PCMCIA function */
  164         void *sc_ih;                            /* interrupt handler */
  165 };
  166 
  167 #if NCOM
  168 struct cfattach com_pcmcia_ca = {
  169         sizeof(struct com_pcmcia_softc), com_pcmcia_match, com_pcmcia_attach,
  170         com_pcmcia_detach, com_pcmcia_activate
  171 };
  172 #elif NPCCOM
  173 struct cfattach pccom_pcmcia_ca = {
  174         sizeof(struct com_pcmcia_softc), com_pcmcia_match, com_pcmcia_attach,
  175         com_pcmcia_detach, com_pcmcia_activate
  176 };
  177 #endif
  178 
  179 int
  180 com_pcmcia_match(parent, match, aux)
  181         struct device *parent;
  182         void *match, *aux;
  183 {
  184         struct pcmcia_attach_args *pa = aux;
  185         struct pcmcia_config_entry *cfe;
  186         int i, j, comportmask;
  187 
  188         /* 1. Does it claim to be a serial device? */
  189         if (pa->pf->function == PCMCIA_FUNCTION_SERIAL)
  190             return 1;
  191 
  192         /* 2. Does it have all four 'standard' port ranges? */
  193         comportmask = 0;
  194         SIMPLEQ_FOREACH(cfe, &pa->pf->cfe_head, cfe_list) {
  195                 switch (cfe->iospace[0].start) {
  196                 case IO_COM1:
  197                         comportmask |= 1;
  198                         break;
  199                 case IO_COM2:
  200                         comportmask |= 2;
  201                         break;
  202                 case IO_COM3:
  203                         comportmask |= 4;
  204                         break;
  205                 case IO_COM4:
  206                         comportmask |= 8;
  207                         break;
  208                 }
  209         }
  210 
  211         if (comportmask == 15)
  212                 return 1;
  213 
  214         /* 3. Is this a card we know about? */
  215         for (i = 0; i < sizeof(com_pcmcia_prod)/sizeof(com_pcmcia_prod[0]);
  216             i++) {
  217                 for (j = 0; j < 4; j++)
  218                         if (com_pcmcia_prod[i].cis1_info[j] &&
  219                             pa->card->cis1_info[j] &&
  220                             strcmp(pa->card->cis1_info[j],
  221                             com_pcmcia_prod[i].cis1_info[j]))
  222                                 break;
  223                 if (j == 4)
  224                         return 1;
  225         }
  226 
  227         return 0;
  228 }
  229 
  230 int
  231 com_pcmcia_activate(dev, act)
  232         struct device *dev;
  233         enum devact act;
  234 {
  235         struct com_pcmcia_softc *sc = (void *) dev;
  236         int s;
  237 
  238         s = spltty();
  239         switch (act) {
  240         case DVACT_ACTIVATE:
  241                 pcmcia_function_enable(sc->sc_pf);
  242                 sc->sc_ih = pcmcia_intr_establish(sc->sc_pf, IPL_TTY,
  243                     comintr, sc, sc->sc_com.sc_dev.dv_xname);
  244                 break;
  245 
  246         case DVACT_DEACTIVATE:
  247                 pcmcia_intr_disestablish(sc->sc_pf, sc->sc_ih);
  248                 pcmcia_function_disable(sc->sc_pf);
  249                 break;
  250         }
  251         splx(s);
  252         return (0);
  253 }
  254 
  255 void
  256 com_pcmcia_attach(parent, self, aux)
  257         struct device *parent, *self;
  258         void *aux;
  259 {
  260         struct com_pcmcia_softc *psc = (void *) self;
  261         struct com_softc *sc = &psc->sc_com;
  262         struct pcmcia_attach_args *pa = aux;
  263         struct pcmcia_config_entry *cfe;
  264         const char *intrstr;
  265         int autoalloc = 0;
  266 
  267         psc->sc_pf = pa->pf;
  268 
  269 retry:
  270         /* find a cfe we can use */
  271 
  272         for (cfe = SIMPLEQ_FIRST(&pa->pf->cfe_head); cfe;
  273              cfe = SIMPLEQ_NEXT(cfe, cfe_list)) {
  274 #if 0
  275                 /*
  276                  * Some modem cards (e.g. Xircom CM33) also have
  277                  * mem space.  Don't bother with this check.
  278                  */
  279                 if (cfe->num_memspace != 0)
  280                         continue;
  281 #endif
  282 
  283                 if (cfe->num_iospace != 1)
  284                         continue;
  285 
  286                 if (!pcmcia_io_alloc(pa->pf,
  287                     autoalloc ? 0 : cfe->iospace[0].start,
  288                     cfe->iospace[0].length, COM_NPORTS, &psc->sc_pcioh)) {
  289                         goto found;
  290                 }
  291         }
  292         if (autoalloc == 0) {
  293                 autoalloc = 1;
  294                 goto retry;
  295         } else if (!cfe) {
  296                 printf(": can't allocate i/o space\n");
  297                 return;
  298         }
  299 
  300 found:
  301         sc->sc_iot = psc->sc_pcioh.iot;
  302         sc->sc_ioh = psc->sc_pcioh.ioh;
  303 
  304         /* Enable the card. */
  305         pcmcia_function_init(pa->pf, cfe);
  306         if (com_pcmcia_enable1(sc))
  307                 printf(": function enable failed\n");
  308 
  309         sc->enabled = 1;
  310 
  311         /* map in the io space */
  312 
  313         if (pcmcia_io_map(pa->pf, ((cfe->flags & PCMCIA_CFE_IO16) ?
  314             PCMCIA_WIDTH_IO16 : PCMCIA_WIDTH_IO8), 0, psc->sc_pcioh.size,
  315             &psc->sc_pcioh, &psc->sc_io_window)) {
  316                 printf(": can't map i/o space\n");
  317                 return;
  318         }
  319 
  320         printf(" port 0x%lx/%lu", psc->sc_pcioh.addr,
  321             (u_long)psc->sc_pcioh.size);
  322 
  323         sc->sc_iobase = -1;
  324         sc->enable = com_pcmcia_enable;
  325         sc->disable = com_pcmcia_disable;
  326         sc->sc_frequency = COM_FREQ;
  327 
  328         sc->sc_hwflags = 0;
  329         sc->sc_swflags = 0;
  330 
  331         if (psc->sc_pf->sc->card.manufacturer == PCMCIA_VENDOR_AUDIOVOX &&
  332             psc->sc_pf->sc->card.product == PCMCIA_PRODUCT_AUDIOVOX_RTM8000)
  333                 sc->sc_fifolen = 16;
  334 
  335         com_attach_subr(sc);
  336 
  337         /* establish the interrupt. */
  338         psc->sc_ih = pcmcia_intr_establish(pa->pf, IPL_TTY, comintr, sc,
  339             sc->sc_dev.dv_xname);
  340         intrstr = pcmcia_intr_string(psc->sc_pf, psc->sc_ih);
  341         if (*intrstr)
  342                 printf(", %s", intrstr);
  343 
  344 #ifdef notyet
  345         sc->enabled = 0;
  346 
  347         com_pcmcia_disable1(sc);
  348 #endif
  349 }
  350 
  351 int
  352 com_pcmcia_detach(dev, flags)
  353         struct device *dev;
  354         int flags;
  355 {
  356         struct com_pcmcia_softc *psc = (struct com_pcmcia_softc *)dev;
  357         int error;
  358 
  359         /* Release all resources.  */
  360         error = com_detach(dev, flags);
  361         if (error)
  362             return (error);
  363 
  364         pcmcia_io_unmap(psc->sc_pf, psc->sc_io_window);
  365         pcmcia_io_free(psc->sc_pf, &psc->sc_pcioh);
  366 
  367         return (0);
  368 }
  369 
  370 int
  371 com_pcmcia_enable(sc)
  372         struct com_softc *sc;
  373 {
  374         struct com_pcmcia_softc *psc = (struct com_pcmcia_softc *) sc;
  375         struct pcmcia_function *pf = psc->sc_pf;
  376 
  377         /* establish the interrupt. */
  378         psc->sc_ih = pcmcia_intr_establish(pf, IPL_TTY, comintr, sc,
  379             sc->sc_dev.dv_xname);
  380         if (psc->sc_ih == NULL) {
  381                 printf("%s: couldn't establish interrupt\n",
  382                     sc->sc_dev.dv_xname);
  383                 return (1);
  384         }
  385         return com_pcmcia_enable1(sc);
  386 }
  387 
  388 int
  389 com_pcmcia_enable1(sc)
  390         struct com_softc *sc;
  391 {
  392         struct com_pcmcia_softc *psc = (struct com_pcmcia_softc *) sc;
  393         struct pcmcia_function *pf = psc->sc_pf;
  394         int ret;
  395 
  396         if ((ret = pcmcia_function_enable(pf)))
  397             return(ret);
  398 
  399         if ((psc->sc_pf->sc->card.product == PCMCIA_PRODUCT_3COM_3C562) ||
  400             (psc->sc_pf->sc->card.product == PCMCIA_PRODUCT_3COM_3CXEM556) ||
  401             (psc->sc_pf->sc->card.product == PCMCIA_PRODUCT_3COM_3CXEM556B)) {
  402                 int reg;
  403 
  404                 /* turn off the ethernet-disable bit */
  405 
  406                 reg = pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION);
  407                 if (reg & 0x08) {
  408                     reg &= ~0x08;
  409                     pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
  410                 }
  411         }
  412 
  413         return(ret);
  414 }
  415 
  416 void
  417 com_pcmcia_disable(sc)
  418         struct com_softc *sc;
  419 {
  420         struct com_pcmcia_softc *psc = (struct com_pcmcia_softc *) sc;
  421 
  422         pcmcia_intr_disestablish(psc->sc_pf, psc->sc_ih);
  423         com_pcmcia_disable1(sc);
  424 }
  425 
  426 void
  427 com_pcmcia_disable1(sc)
  428         struct com_softc *sc;
  429 {
  430         struct com_pcmcia_softc *psc = (struct com_pcmcia_softc *) sc;
  431 
  432         pcmcia_function_disable(psc->sc_pf);
  433 }

/* [<][>][^][v][top][bottom][index][help] */