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/isa/isa.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: isa.c,v 1.116 2003/01/01 00:10:20 thorpej Exp $        */
    2 
    3 /*-
    4  * Copyright (c) 1998, 2001 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Charles M. Hannum; by Jason R. Thorpe of Wasabi Systems, Inc.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. All advertising materials mentioning features or use of this software
   19  *    must display the following acknowledgement:
   20  *        This product includes software developed by the NetBSD
   21  *        Foundation, Inc. and its contributors.
   22  * 4. Neither the name of The NetBSD Foundation nor the names of its
   23  *    contributors may be used to endorse or promote products derived
   24  *    from this software without specific prior written permission.
   25  *
   26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   36  * POSSIBILITY OF SUCH DAMAGE.
   37  */
   38 
   39 #include <sys/cdefs.h>
   40 __KERNEL_RCSID(0, "$NetBSD: isa.c,v 1.116 2003/01/01 00:10:20 thorpej Exp $");
   41 
   42 #include <sys/param.h>
   43 #include <sys/systm.h>
   44 #include <sys/kernel.h>
   45 #include <sys/malloc.h>
   46 #include <sys/device.h>
   47 
   48 #include <machine/intr.h>
   49 
   50 #include <dev/isa/isareg.h>
   51 #include <dev/isa/isavar.h>
   52 #include <dev/isa/isadmareg.h>
   53 
   54 #include "isadma.h"
   55 
   56 #include "isapnp.h"
   57 #if NISAPNP > 0
   58 #include <dev/isapnp/isapnpreg.h>
   59 #include <dev/isapnp/isapnpvar.h>
   60 #endif
   61 
   62 int     isamatch(struct device *, struct cfdata *, void *);
   63 void    isaattach(struct device *, struct device *, void *);
   64 int     isaprint(void *, const char *);
   65 
   66 CFATTACH_DECL(isa, sizeof(struct isa_softc),
   67     isamatch, isaattach, NULL, NULL);
   68 
   69 void    isa_attach_knowndevs(struct isa_softc *);
   70 void    isa_free_knowndevs(struct isa_softc *);
   71 
   72 int     isasubmatch(struct device *, struct cfdata *, void *);
   73 int     isasearch(struct device *, struct cfdata *, void *);
   74 
   75 int
   76 isamatch(struct device *parent, struct cfdata *cf, void *aux)
   77 {
   78         struct isabus_attach_args *iba = aux;
   79 
   80         if (strcmp(iba->iba_busname, cf->cf_name))
   81                 return (0);
   82 
   83         /* XXX check other indicators */
   84 
   85         return (1);
   86 }
   87 
   88 void
   89 isaattach(struct device *parent, struct device *self, void *aux)
   90 {
   91         struct isa_softc *sc = (struct isa_softc *)self;
   92         struct isabus_attach_args *iba = aux;
   93 
   94         TAILQ_INIT(&sc->sc_knowndevs);
   95         sc->sc_dynamicdevs = 0;
   96 
   97         isa_attach_hook(parent, self, iba);
   98         printf("\n");
   99 
  100         /* XXX Add code to fetch known-devices. */
  101 
  102         sc->sc_iot = iba->iba_iot;
  103         sc->sc_memt = iba->iba_memt;
  104         sc->sc_dmat = iba->iba_dmat;
  105         sc->sc_ic = iba->iba_ic;
  106 
  107 #if NISAPNP > 0
  108         /*
  109          * Reset isapnp cards that the bios configured for us
  110          */
  111         isapnp_isa_attach_hook(sc);
  112 #endif
  113 
  114 #if NISADMA > 0
  115         /*
  116          * Initialize our DMA state.
  117          */
  118         isa_dmainit(sc->sc_ic, sc->sc_iot, sc->sc_dmat, self);
  119 #endif
  120 
  121         /* Attach all direct-config children. */
  122         isa_attach_knowndevs(sc);
  123 
  124         /*
  125          * If we don't support dynamic hello/goodbye of devices,
  126          * then free the knowndevs info now.
  127          */
  128         if (sc->sc_dynamicdevs == 0)
  129                 isa_free_knowndevs(sc);
  130 
  131         /* Attach all indrect-config children. */
  132         config_search(isasearch, self, NULL);
  133 }
  134 
  135 void
  136 isa_attach_knowndevs(struct isa_softc *sc)
  137 {
  138         struct isa_attach_args ia;
  139         struct isa_knowndev *ik;
  140 
  141         if (TAILQ_EMPTY(&sc->sc_knowndevs))
  142                 return;
  143 
  144         TAILQ_FOREACH(ik, &sc->sc_knowndevs, ik_list) {
  145                 if (ik->ik_claimed != NULL)
  146                         continue;
  147 
  148                 ia.ia_iot = sc->sc_iot;
  149                 ia.ia_memt = sc->sc_memt;
  150                 ia.ia_dmat = sc->sc_dmat;
  151                 ia.ia_ic = sc->sc_ic;
  152 
  153                 ia.ia_pnpname = ik->ik_pnpname;
  154                 ia.ia_pnpcompatnames = ik->ik_pnpcompatnames;
  155 
  156                 ia.ia_io = ik->ik_io;
  157                 ia.ia_nio = ik->ik_nio;
  158 
  159                 ia.ia_iomem = ik->ik_iomem;
  160                 ia.ia_niomem = ik->ik_niomem;
  161 
  162                 ia.ia_irq = ik->ik_irq;
  163                 ia.ia_nirq = ik->ik_nirq;
  164 
  165                 ia.ia_drq = ik->ik_drq;
  166                 ia.ia_ndrq = ik->ik_ndrq;
  167 
  168                 ia.ia_aux = NULL;
  169 
  170                 ik->ik_claimed = config_found_sm(&sc->sc_dev, &ia,
  171                     isaprint, isasubmatch);
  172         }
  173 }
  174 
  175 void
  176 isa_free_knowndevs(struct isa_softc *sc)
  177 {
  178         struct isa_knowndev *ik;
  179         struct isa_pnpname *ipn;
  180 
  181 #define FREEIT(x)       if (x != NULL) free(x, M_DEVBUF)
  182 
  183         while ((ik = TAILQ_FIRST(&sc->sc_knowndevs)) != NULL) {
  184                 TAILQ_REMOVE(&sc->sc_knowndevs, ik, ik_list);
  185                 FREEIT(ik->ik_pnpname);
  186                 while ((ipn = ik->ik_pnpcompatnames) != NULL) {
  187                         ik->ik_pnpcompatnames = ipn->ipn_next;
  188                         free(ipn->ipn_name, M_DEVBUF);
  189                         free(ipn, M_DEVBUF);
  190                 }
  191                 FREEIT(ik->ik_io);
  192                 FREEIT(ik->ik_iomem);
  193                 FREEIT(ik->ik_irq);
  194                 FREEIT(ik->ik_drq);
  195                 free(ik, M_DEVBUF);
  196         }
  197 
  198 #undef FREEIT
  199 }
  200 
  201 int
  202 isasubmatch(struct device *parent, struct cfdata *cf, void *aux)
  203 {
  204         struct isa_attach_args *ia = aux;
  205         int i;
  206 
  207         if (ia->ia_nio == 0) {
  208                 if (cf->cf_iobase != ISACF_PORT_DEFAULT)
  209                         return (0);
  210         } else {
  211                 if (cf->cf_iobase != ISACF_PORT_DEFAULT &&
  212                     cf->cf_iobase != ia->ia_io[0].ir_addr)
  213                         return (0);
  214         }
  215 
  216         if (ia->ia_niomem == 0) {
  217                 if (cf->cf_maddr != ISACF_IOMEM_DEFAULT)
  218                         return (0);
  219         } else {
  220                 if (cf->cf_maddr != ISACF_IOMEM_DEFAULT &&
  221                     cf->cf_maddr != ia->ia_iomem[0].ir_addr)
  222                         return (0);
  223         }
  224 
  225         if (ia->ia_nirq == 0) {
  226                 if (cf->cf_irq != ISACF_IRQ_DEFAULT)
  227                         return (0);
  228         } else {
  229                 if (cf->cf_irq != ISACF_IRQ_DEFAULT &&
  230                     cf->cf_irq != ia->ia_irq[0].ir_irq)
  231                         return (0);
  232         }
  233 
  234         if (ia->ia_ndrq == 0) {
  235                 if (cf->cf_drq != ISACF_DRQ_DEFAULT)
  236                         return (0);
  237                 if (cf->cf_drq2 != ISACF_DRQ_DEFAULT)
  238                         return (0);
  239         } else {
  240                 for (i = 0; i < 2; i++) {
  241                         if (i == ia->ia_ndrq)
  242                                 break;
  243                         if (cf->cf_loc[ISACF_DRQ + i] != ISACF_DRQ_DEFAULT &&
  244                             cf->cf_loc[ISACF_DRQ + i] != ia->ia_drq[i].ir_drq)
  245                                 return (0);
  246                 }
  247                 for (; i < 2; i++) {
  248                         if (cf->cf_loc[ISACF_DRQ + i] != ISACF_DRQ_DEFAULT)
  249                                 return (0);
  250                 }
  251         }
  252 
  253         return (config_match(parent, cf, aux));
  254 }
  255 
  256 int
  257 isaprint(void *aux, const char *isa)
  258 {
  259         struct isa_attach_args *ia = aux;
  260         const char *sep;
  261         int i;
  262 
  263         /*
  264          * This block of code only fires if we have a direct-config'd
  265          * device for which there is no driver match.
  266          */
  267         if (isa != NULL) {
  268                 struct isa_pnpname *ipn;
  269 
  270                 if (ia->ia_pnpname != NULL)
  271                         aprint_normal("%s", ia->ia_pnpname);
  272                 if ((ipn = ia->ia_pnpcompatnames) != NULL) {
  273                         aprint_normal(" (");    /* ) */
  274                         for (sep = ""; ipn != NULL;
  275                              ipn = ipn->ipn_next, sep = " ") {
  276                                 aprint_normal("%s%s", sep, ipn->ipn_name);
  277                         }
  278         /* ( */         aprint_normal(")");
  279                 }
  280                 aprint_normal(" at %s", isa);
  281         }
  282 
  283         if (ia->ia_nio) {
  284                 sep = "";
  285                 aprint_normal(" port ");
  286                 for (i = 0; i < ia->ia_nio; i++) {
  287                         if (ia->ia_io[i].ir_size == 0)
  288                                 continue;
  289                         aprint_normal("%s0x%x", sep, ia->ia_io[i].ir_addr);
  290                         if (ia->ia_io[i].ir_size > 1)
  291                                 aprint_normal("-0x%x", ia->ia_io[i].ir_addr +
  292                                     ia->ia_io[i].ir_size - 1);
  293                         sep = ",";
  294                 }
  295         }
  296 
  297         if (ia->ia_niomem) {
  298                 sep = "";
  299                 aprint_normal(" iomem ");
  300                 for (i = 0; i < ia->ia_niomem; i++) {
  301                         if (ia->ia_iomem[i].ir_size == 0)
  302                                 continue;
  303                         aprint_normal("%s0x%x", sep, ia->ia_iomem[i].ir_addr);
  304                         if (ia->ia_iomem[i].ir_size > 1)
  305                                 aprint_normal("-0x%x", ia->ia_iomem[i].ir_addr +
  306                                     ia->ia_iomem[i].ir_size - 1);
  307                         sep = ",";
  308                 }
  309         }
  310 
  311         if (ia->ia_nirq) {
  312                 sep = "";
  313                 aprint_normal(" irq ");
  314                 for (i = 0; i < ia->ia_nirq; i++) {
  315                         if (ia->ia_irq[i].ir_irq == ISACF_IRQ_DEFAULT)
  316                                 continue;
  317                         aprint_normal("%s%d", sep, ia->ia_irq[i].ir_irq);
  318                         sep = ",";
  319                 }
  320         }
  321 
  322         if (ia->ia_ndrq) {
  323                 sep = "";
  324                 aprint_normal(" drq ");
  325                 for (i = 0; i < ia->ia_ndrq; i++) {
  326                         if (ia->ia_drq[i].ir_drq == ISACF_DRQ_DEFAULT)
  327                                 continue;
  328                         aprint_normal("%s%d", sep, ia->ia_drq[i].ir_drq);
  329                         sep = ",";
  330                 }
  331         }
  332 
  333         return (UNCONF);
  334 }
  335 
  336 int
  337 isasearch(struct device *parent, struct cfdata *cf, void *aux)
  338 {
  339         struct isa_io res_io[1];
  340         struct isa_iomem res_mem[1];
  341         struct isa_irq res_irq[1];
  342         struct isa_drq res_drq[2];
  343         struct isa_softc *sc = (struct isa_softc *)parent;
  344         struct isa_attach_args ia;
  345         int tryagain;
  346 
  347         do {
  348                 ia.ia_pnpname = NULL;
  349                 ia.ia_pnpcompatnames = NULL;
  350 
  351                 res_io[0].ir_addr = cf->cf_loc[ISACF_PORT];
  352                 res_io[0].ir_size = 0;
  353 
  354                 res_mem[0].ir_addr = cf->cf_loc[ISACF_IOMEM];
  355                 res_mem[0].ir_size = cf->cf_loc[ISACF_IOSIZ];
  356 
  357                 res_irq[0].ir_irq =
  358                     cf->cf_loc[ISACF_IRQ] == 2 ? 9 : cf->cf_loc[ISACF_IRQ];
  359 
  360                 res_drq[0].ir_drq = cf->cf_loc[ISACF_DRQ];
  361                 res_drq[1].ir_drq = cf->cf_loc[ISACF_DRQ2];
  362 
  363                 ia.ia_iot = sc->sc_iot;
  364                 ia.ia_memt = sc->sc_memt;
  365                 ia.ia_dmat = sc->sc_dmat;
  366                 ia.ia_ic = sc->sc_ic;
  367 
  368                 ia.ia_io = res_io;
  369                 ia.ia_nio = 1;
  370 
  371                 ia.ia_iomem = res_mem;
  372                 ia.ia_niomem = 1;
  373 
  374                 ia.ia_irq = res_irq;
  375                 ia.ia_nirq = 1;
  376 
  377                 ia.ia_drq = res_drq;
  378                 ia.ia_ndrq = 2;
  379 
  380                 tryagain = 0;
  381                 if (config_match(parent, cf, &ia) > 0) {
  382                         config_attach(parent, cf, &ia, isaprint);
  383                         tryagain = (cf->cf_fstate == FSTATE_STAR);
  384                 }
  385         } while (tryagain);
  386 
  387         return (0);
  388 }
  389 
  390 char *
  391 isa_intr_typename(int type)
  392 {
  393 
  394         switch (type) {
  395         case IST_NONE :
  396                 return ("none");
  397         case IST_PULSE:
  398                 return ("pulsed");
  399         case IST_EDGE:
  400                 return ("edge-triggered");
  401         case IST_LEVEL:
  402                 return ("level-triggered");
  403         default:
  404                 panic("isa_intr_typename: invalid type %d", type);
  405         }
  406 }

Cache object: 5ccd2648b71f79423da7e63b210683d1


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