root/dev/isa/tcic2_isa.c

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

DEFINITIONS

This source file includes following definitions.
  1. tcic_isa_probe
  2. tcic_isa_attach
  3. tcic_isa_chip_intr_establish
  4. tcic_isa_chip_intr_disestablish
  5. tcic_isa_chip_intr_string

    1 /*      $OpenBSD: tcic2_isa.c,v 1.7 2005/01/27 17:03:23 millert Exp $   */
    2 /*      $NetBSD: tcic2_isa.c,v 1.2 1999/04/08 16:14:29 bad Exp $        */
    3 
    4 #undef  TCICISADEBUG
    5 
    6 /*
    7  *
    8  * Copyright (c) 1998, 1999 Christoph Badura. All rights reserved.
    9  * Copyright (c) 1997 Marc Horowitz.  All rights reserved.
   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 Marc Horowitz.
   22  * 4. 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 
   37 
   38 #include <sys/types.h>
   39 #include <sys/param.h>
   40 #include <sys/systm.h>
   41 #include <sys/device.h>
   42 #include <sys/extent.h>
   43 #include <sys/malloc.h>
   44 
   45 #include <machine/bus.h>
   46 #include <machine/intr.h>
   47 
   48 #include <dev/isa/isareg.h>
   49 #include <dev/isa/isavar.h>
   50 
   51 #include <dev/pcmcia/pcmciareg.h>
   52 #include <dev/pcmcia/pcmciavar.h>
   53 #include <dev/pcmcia/pcmciachip.h>
   54 
   55 #include <dev/ic/tcic2reg.h>
   56 #include <dev/ic/tcic2var.h>
   57 
   58 /*****************************************************************************
   59  * Configurable parameters.
   60  *****************************************************************************/
   61 
   62 /*
   63  * Default I/O allocation range.  If both are set to non-zero, these
   64  * values will be used instead.  Otherwise, the code attempts to probe
   65  * the bus width.  Systems with 10 address bits should use 0x300 and 0xff.
   66  * Systems with 12 address bits (most) should use 0x400 and 0xbff.
   67  */
   68 
   69 #ifndef TCIC_ISA_ALLOC_IOBASE
   70 #define TCIC_ISA_ALLOC_IOBASE           0
   71 #endif
   72 
   73 #ifndef TCIC_ISA_ALLOC_IOSIZE
   74 #define TCIC_ISA_ALLOC_IOSIZE           0
   75 #endif
   76 
   77 int     tcic_isa_alloc_iobase = TCIC_ISA_ALLOC_IOBASE;
   78 int     tcic_isa_alloc_iosize = TCIC_ISA_ALLOC_IOSIZE;
   79 
   80 /*
   81  * Default IRQ allocation bitmask.  This defines the range of allowable
   82  * IRQs for PCMCIA slots.  Useful if order of probing would screw up other
   83  * devices, or if TCIC hardware/cards have trouble with certain interrupt
   84  * lines.
   85  *
   86  * We disable IRQ 10 by default, since some common laptops (namely, the
   87  * NEC Versa series) reserve IRQ 10 for the docking station SCSI interface.
   88  *
   89  * XXX Do we care about this?  the Versa doesn't use a tcic. -chb
   90  */
   91 
   92 #ifndef TCIC_ISA_INTR_ALLOC_MASK
   93 #define TCIC_ISA_INTR_ALLOC_MASK        0xffff
   94 #endif
   95 
   96 int     tcic_isa_intr_alloc_mask = TCIC_ISA_INTR_ALLOC_MASK;
   97 
   98 /*****************************************************************************
   99  * End of configurable parameters.
  100  *****************************************************************************/
  101 
  102 #ifdef TCICISADEBUG
  103 int     tcic_isa_debug = 1;
  104 #define DPRINTF(arg) if (tcic_isa_debug) printf arg;
  105 #else
  106 #define DPRINTF(arg)
  107 #endif
  108 
  109 int     tcic_isa_probe(struct device *, void *, void *);
  110 void    tcic_isa_attach(struct device *, struct device *, void *);
  111 
  112 void    *tcic_isa_chip_intr_establish(pcmcia_chipset_handle_t,
  113             struct pcmcia_function *, int, int (*) (void *), void *, char *);
  114 void    tcic_isa_chip_intr_disestablish(pcmcia_chipset_handle_t, void *);
  115 const char *tcic_isa_chip_intr_string(pcmcia_chipset_handle_t, void *);
  116 
  117 struct cfattach tcic_isa_ca = {
  118         sizeof(struct tcic_softc), tcic_isa_probe, tcic_isa_attach
  119 };
  120 
  121 static struct pcmcia_chip_functions tcic_isa_functions = {
  122         tcic_chip_mem_alloc,
  123         tcic_chip_mem_free,
  124         tcic_chip_mem_map,
  125         tcic_chip_mem_unmap,
  126 
  127         tcic_chip_io_alloc,
  128         tcic_chip_io_free,
  129         tcic_chip_io_map,
  130         tcic_chip_io_unmap,
  131 
  132         tcic_isa_chip_intr_establish,
  133         tcic_isa_chip_intr_disestablish,
  134         tcic_isa_chip_intr_string,
  135 
  136         tcic_chip_socket_enable,
  137         tcic_chip_socket_disable,
  138 };
  139 
  140 int
  141 tcic_isa_probe(parent, match, aux)
  142         struct device *parent;
  143         void *match;
  144         void *aux;
  145 {
  146         struct isa_attach_args *ia = aux;
  147         bus_space_tag_t iot = ia->ia_iot;
  148         bus_space_handle_t ioh, memh;
  149         int val, found;
  150 
  151         /* Disallow wildcarded i/o address. */
  152         if (ia->ia_iobase == -1 /* ISACF_PORT_DEFAULT */)
  153                 return (0);
  154 
  155         if (bus_space_map(iot, ia->ia_iobase, TCIC_IOSIZE, 0, &ioh))
  156                 return (0);
  157 
  158         if (ia->ia_msize == 0)
  159                 ia->ia_msize = TCIC_MEMSIZE;
  160 
  161         if (bus_space_map(ia->ia_memt, ia->ia_maddr, ia->ia_msize, 0, &memh))
  162                 return (0);
  163 
  164         DPRINTF(("tcic probing 0x%03x\n", ia->ia_iobase));
  165         found = 0;
  166 
  167         /*
  168          * First, check for the reserved bits to be zero.
  169          */
  170         if (tcic_check_reserved_bits(iot, ioh)) {
  171                 DPRINTF(("tcic: reserved bits checked OK\n"));
  172                 /* Second, check whether the we know how to handle the chip. */
  173                 if ((val = tcic_chipid(iot, ioh))) {
  174                         DPRINTF(("tcic id: 0x%02x\n", val));
  175                         if (tcic_chipid_known(val))
  176                                 found++;
  177                 }
  178         }
  179         else
  180                 DPRINTF(("tcic: reserved bits didn't check OK\n"));
  181 
  182         bus_space_unmap(iot, ioh, TCIC_IOSIZE);
  183         bus_space_unmap(ia->ia_memt, memh, ia->ia_msize);
  184 
  185         if (!found)
  186                 return (0);
  187 
  188         ia->ia_iosize = TCIC_IOSIZE;
  189 
  190         return (1);
  191 }
  192 
  193 void
  194 tcic_isa_attach(parent, self, aux)
  195         struct device *parent, *self;
  196         void *aux;
  197 {
  198         struct tcic_softc *sc = (void *) self;
  199         struct isa_attach_args *ia = aux;
  200         isa_chipset_tag_t ic = ia->ia_ic;
  201         bus_space_tag_t iot = ia->ia_iot;
  202         bus_space_tag_t memt = ia->ia_memt;
  203         bus_space_handle_t ioh;
  204         bus_space_handle_t memh;
  205 
  206         /* Map i/o space. */
  207         if (bus_space_map(iot, ia->ia_iobase, ia->ia_iosize, 0, &ioh)) {
  208                 printf(": can't map i/o space\n");
  209                 return;
  210         }
  211 
  212         /* Map mem space. */
  213         if (bus_space_map(memt, ia->ia_maddr, ia->ia_msize, 0, &memh)) {
  214                 printf(": can't map mem space\n");
  215                 return;
  216         }
  217 
  218         sc->membase = ia->ia_maddr;
  219         sc->subregionmask = (1 << (ia->ia_msize / TCIC_MEM_PAGESIZE)) - 1;
  220         sc->memsize2 = tcic_log2((u_int)ia->ia_msize);
  221 
  222         sc->intr_est = ic;
  223         sc->pct = (pcmcia_chipset_tag_t) &tcic_isa_functions;
  224 
  225         sc->iot = iot;
  226         sc->ioh = ioh;
  227         sc->memt = memt;
  228         sc->memh = memh;
  229 
  230         /*
  231          * determine chip type and initialise some chip type dependend
  232          * parameters in softc.
  233          */
  234         sc->chipid = tcic_chipid(iot, ioh);
  235         sc->validirqs = tcic_validirqs(sc->chipid);
  236 
  237         /*
  238          * allocate an irq.  interrupts are relatively
  239          * scarce but for TCIC controllers very infrequent.
  240          */
  241 
  242         if ((sc->irq = ia->ia_irq) == IRQUNK) {
  243                 if (isa_intr_alloc(ic,
  244                     sc->validirqs & (tcic_isa_intr_alloc_mask & 0xff00),
  245                     IST_EDGE, &sc->irq)) {
  246                         printf("\n%s: can't allocate interrupt\n",
  247                             sc->dev.dv_xname);
  248                         return;
  249                 }
  250                 printf(": using irq %d", sc->irq);
  251         }
  252         printf("\n");
  253 
  254         tcic_attach(sc);
  255 
  256 
  257         /*
  258          * XXX mycroft recommends I/O space range 0x400-0xfff.
  259          */
  260 
  261         /*
  262          * XXX some hardware doesn't seem to grok addresses in 0x400 range--
  263          * apparently missing a bit or more of address lines. (e.g.
  264          * CIRRUS_PD672X with Linksys EthernetCard ne2000 clone in TI
  265          * TravelMate 5000--not clear which is at fault)
  266          * 
  267          * Add a kludge to detect 10 bit wide buses and deal with them,
  268          * and also a config file option to override the probe.
  269          */
  270 
  271 #if 0
  272         /*
  273          * This is what we'd like to use, but...
  274          */
  275         sc->iobase = 0x400;
  276         sc->iosize = 0xbff;
  277 #else
  278         /*
  279          * ...the above bus width probe doesn't always work.
  280          * So, experimentation has shown the following range
  281          * to not lose on systems that 0x300-0x3ff loses on
  282          * (e.g. the NEC Versa 6030X).
  283          */
  284         sc->iobase = 0x330;
  285         sc->iosize = 0x0cf;
  286 #endif
  287 
  288         DPRINTF(("%s: bus_space_alloc range 0x%04lx-0x%04lx)\n",
  289             sc->dev.dv_xname, (long) sc->iobase,
  290             (long) sc->iobase + sc->iosize));
  291 
  292         if (tcic_isa_alloc_iobase && tcic_isa_alloc_iosize) {
  293                 sc->iobase = tcic_isa_alloc_iobase;
  294                 sc->iosize = tcic_isa_alloc_iosize;
  295 
  296                 DPRINTF(("%s: bus_space_alloc range 0x%04lx-0x%04lx "
  297                     "(config override)\n", sc->dev.dv_xname, (long) sc->iobase,
  298                     (long) sc->iobase + sc->iosize));
  299         }
  300         sc->ih = isa_intr_establish(ic, sc->irq, IST_EDGE, IPL_TTY,
  301             tcic_intr, sc, sc->dev.dv_xname);
  302         if (sc->ih == NULL) {
  303                 printf("%s: can't establish interrupt\n", sc->dev.dv_xname);
  304                 return;
  305         }
  306 
  307         tcic_attach_sockets(sc);
  308 }
  309 
  310 void *
  311 tcic_isa_chip_intr_establish(pch, pf, ipl, fct, arg, xname)
  312         pcmcia_chipset_handle_t pch;
  313         struct pcmcia_function *pf;
  314         int ipl;
  315         int (*fct)(void *);
  316         void *arg;
  317         char *xname;
  318 {
  319         struct tcic_handle *h = (struct tcic_handle *) pch;
  320         int irq, ist, val, reg;
  321         void *ih;
  322         int irqmap[] = {
  323             0, 0, 0, TCIC_SCF1_IRQ3, TCIC_SCF1_IRQ4, TCIC_SCF1_IRQ5,
  324             TCIC_SCF1_IRQ6, TCIC_SCF1_IRQ7, 0, TCIC_SCF1_IRQ9,
  325             TCIC_SCF1_IRQ10, TCIC_SCF1_IRQ11, TCIC_SCF1_IRQ12, 0,
  326             TCIC_SCF1_IRQ14, TCIC_SCF1_IRQ15
  327         };
  328 
  329         DPRINTF(("%s: tcic_isa_chip_intr_establish\n", h->sc->dev.dv_xname));
  330 
  331         /* XXX should we convert level to pulse? -chb  */
  332         if (pf->cfe->flags & PCMCIA_CFE_IRQLEVEL)
  333                 ist = IST_LEVEL;
  334         else if (pf->cfe->flags & PCMCIA_CFE_IRQPULSE)
  335                 ist = IST_PULSE;
  336         else
  337                 ist = IST_LEVEL;
  338 
  339         if (isa_intr_alloc(h->sc->intr_est,
  340             h->sc->validirqs & tcic_isa_intr_alloc_mask, ist, &irq))
  341                 return (NULL);
  342         if ((ih = isa_intr_establish(h->sc->intr_est, irq, ist, ipl,
  343             fct, arg, h->pcmcia->dv_xname)) == NULL)
  344                 return (NULL);
  345 
  346         DPRINTF(("%s: intr established\n", h->sc->dev.dv_xname));
  347 
  348         h->ih_irq = irq;
  349 
  350         reg = TCIC_IR_SCF1_N(h->sock);
  351         val = (tcic_read_ind_2(h, reg) & (~TCIC_SCF1_IRQ_MASK)) | irqmap[irq];
  352         tcic_write_ind_2(h, reg, val);
  353 
  354         printf(" irq %d", irq);
  355         return (ih);
  356 }
  357 
  358 void 
  359 tcic_isa_chip_intr_disestablish(pch, ih)
  360         pcmcia_chipset_handle_t pch;
  361         void *ih;
  362 {
  363         struct tcic_handle *h = (struct tcic_handle *) pch;
  364         int val, reg;
  365 
  366         DPRINTF(("%s: tcic_isa_chip_intr_disestablish\n", h->sc->dev.dv_xname));
  367 
  368         h->ih_irq = 0;
  369 
  370         reg = TCIC_IR_SCF1_N(h->sock);
  371         val = tcic_read_ind_2(h, reg);
  372         val &= ~TCIC_SCF1_IRQ_MASK;
  373         tcic_write_ind_2(h, reg, val);
  374 
  375         isa_intr_disestablish(h->sc->intr_est, ih);
  376 }
  377 
  378 const char *
  379 tcic_isa_chip_intr_string(pch, ih)
  380         pcmcia_chipset_handle_t pch;
  381         void *ih;
  382 {
  383         struct tcic_handle *h = (struct tcic_handle *) pch;
  384         static char irqstr[64];
  385 
  386         if (ih == NULL)
  387                 snprintf(irqstr, sizeof(irqstr), "couldn't establish interrupt");
  388         else
  389                 snprintf(irqstr, sizeof(irqstr), "irq %d", h->ih_irq);
  390         return (irqstr);
  391 }

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