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/pci/isa_pci.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) 1994,1995 Stefan Esser, Wolfgang StanglMeier
    3  * Copyright (c) 2000 Michael Smith <msmith@freebsd.org>
    4  * Copyright (c) 2000 BSDi
    5  * 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. The name of the author may not be used to endorse or promote products
   16  *    derived from this software without specific prior written permission.
   17  *
   18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   28  * SUCH DAMAGE.
   29  */
   30 
   31 #include <sys/cdefs.h>
   32 __FBSDID("$FreeBSD$");
   33 
   34 /*
   35  * PCI:ISA bridge support
   36  */
   37 
   38 #include <sys/param.h>
   39 #include <sys/systm.h>
   40 #include <sys/kernel.h>
   41 #include <sys/module.h>
   42 #include <machine/bus.h>
   43 #include <machine/resource.h>
   44 #include <sys/bus.h>
   45 #include <sys/rman.h>
   46 
   47 #include <isa/isavar.h>
   48 #include <dev/pci/pcivar.h>
   49 #include <dev/pci/pcireg.h>
   50 
   51 #define ELCR_IOADDR     0x4d0   /* Interrupt Edge/Level Control Registers */
   52 #define ELCR_IOLEN      2
   53 
   54 struct isab_softc {
   55     struct resource *elcr_res;
   56     u_char saved_elcr[ELCR_IOLEN];
   57 };
   58 
   59 static int      isab_probe(device_t dev);
   60 static int      pci_isab_attach(device_t dev);
   61 static int      isab_detach(device_t dev);
   62 static int      isab_resume(device_t dev);
   63 static int      isab_suspend(device_t dev);
   64 
   65 static device_method_t isab_methods[] = {
   66     /* Device interface */
   67     DEVMETHOD(device_probe,             isab_probe),
   68     DEVMETHOD(device_attach,            pci_isab_attach),
   69     DEVMETHOD(device_detach,            isab_detach),
   70     DEVMETHOD(device_shutdown,          bus_generic_shutdown),
   71     DEVMETHOD(device_suspend,           isab_suspend),
   72     DEVMETHOD(device_resume,            isab_resume),
   73 
   74     /* Bus interface */
   75     DEVMETHOD(bus_print_child,          bus_generic_print_child),
   76     DEVMETHOD(bus_alloc_resource,       bus_generic_alloc_resource),
   77     DEVMETHOD(bus_release_resource,     bus_generic_release_resource),
   78     DEVMETHOD(bus_activate_resource,    bus_generic_activate_resource),
   79     DEVMETHOD(bus_deactivate_resource,  bus_generic_deactivate_resource),
   80     DEVMETHOD(bus_setup_intr,           bus_generic_setup_intr),
   81     DEVMETHOD(bus_teardown_intr,        bus_generic_teardown_intr),
   82 
   83     { 0, 0 }
   84 };
   85 
   86 static driver_t isab_driver = {
   87     "isab",
   88     isab_methods,
   89     sizeof(struct isab_softc),
   90 };
   91 
   92 DRIVER_MODULE(isab, pci, isab_driver, isab_devclass, 0, 0);
   93 
   94 /*
   95  * XXX we need to add a quirk list here for bridges that don't correctly
   96  *     report themselves.
   97  */
   98 static int
   99 isab_probe(device_t dev)
  100 {
  101     int         matched = 0;
  102 
  103     /*
  104      * Try for a generic match based on class/subclass.
  105      */
  106     if ((pci_get_class(dev) == PCIC_BRIDGE) &&
  107         (pci_get_subclass(dev) == PCIS_BRIDGE_ISA)) {
  108         matched = 1;
  109     } else {
  110         /*
  111          * These are devices that we *know* are PCI:ISA bridges. 
  112          * Sometimes, however, they don't report themselves as
  113          * such.  Check in case one of them is pretending to be
  114          * something else.
  115          */
  116         switch (pci_get_devid(dev)) {
  117         case 0x04848086:        /* Intel 82378ZB/82378IB */
  118         case 0x122e8086:        /* Intel 82371FB */
  119         case 0x70008086:        /* Intel 82371SB */
  120         case 0x71108086:        /* Intel 82371AB */
  121         case 0x71988086:        /* Intel 82443MX */
  122         case 0x24108086:        /* Intel 82801AA (ICH) */
  123         case 0x24208086:        /* Intel 82801AB (ICH0) */
  124         case 0x24408086:        /* Intel 82801AB (ICH2) */
  125         case 0x00061004:        /* VLSI 82C593 */
  126         case 0x05861106:        /* VIA 82C586 */
  127         case 0x05961106:        /* VIA 82C596 */
  128         case 0x06861106:        /* VIA 82C686 */
  129         case 0x153310b9:        /* AcerLabs M1533 */
  130         case 0x154310b9:        /* AcerLabs M1543 */
  131         case 0x00081039:        /* SiS 85c503 */
  132         case 0x00001078:        /* Cyrix Cx5510 */
  133         case 0x01001078:        /* Cyrix Cx5530 */
  134         case 0xc7001045:        /* OPTi 82C700 (FireStar) */
  135         case 0x00011033:        /* NEC 0001 (C-bus) */
  136         case 0x002c1033:        /* NEC 002C (C-bus) */
  137         case 0x003b1033:        /* NEC 003B (C-bus) */
  138         case 0x886a1060:        /* UMC UM8886 ISA */
  139         case 0x02001166:        /* ServerWorks IB6566 PCI */
  140             if (bootverbose)
  141                 printf("PCI-ISA bridge with incorrect subclass 0x%x\n",
  142                        pci_get_subclass(dev));
  143             matched = 1;
  144             break;
  145         
  146         default:
  147             break;
  148         }
  149     }
  150 
  151     if (matched) {
  152         device_set_desc(dev, "PCI-ISA bridge");
  153         return(-10000);
  154     }
  155     return(ENXIO);
  156 }
  157 
  158 static int
  159 pci_isab_attach(device_t dev)
  160 {
  161     struct isab_softc *sc = device_get_softc(dev);
  162     int error, rid;
  163 
  164     /*
  165      * Attach an ISA bus.  Note that we can only have one ISA bus.
  166      */
  167     error = isab_attach(dev);
  168     if (error)
  169             return (error);
  170 
  171     switch (pci_get_devid(dev)) {
  172     case 0x71108086: /* Intel 82371AB */
  173         /*
  174          * Sometimes the ELCR (Edge/Level Control Register) is not restored
  175          * correctly on resume by the BIOS, so we handle it ourselves.
  176          */
  177         rid = 0;
  178         bus_set_resource(dev, SYS_RES_IOPORT, rid, ELCR_IOADDR, ELCR_IOLEN);
  179         sc->elcr_res = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid,
  180             RF_ACTIVE);
  181         if (sc->elcr_res == NULL)
  182             device_printf(dev, "failed to allocate ELCR resource\n");
  183         break;
  184     }
  185 
  186     return(0);
  187 }
  188 
  189 static int
  190 isab_detach(device_t dev)
  191 {
  192     struct isab_softc *sc = device_get_softc(dev);
  193 
  194     if (sc->elcr_res != NULL)
  195         bus_release_resource(dev, SYS_RES_IOPORT, 0, sc->elcr_res);
  196 
  197     return (bus_generic_detach(dev));
  198 }
  199 
  200 static int
  201 isab_suspend(device_t dev)
  202 {
  203     struct isab_softc *sc = device_get_softc(dev);
  204     bus_space_tag_t bst;
  205     bus_space_handle_t bsh;
  206     int i;
  207 
  208     /* Save the ELCR if required. */
  209     if (sc->elcr_res != NULL) {
  210         bst = rman_get_bustag(sc->elcr_res);
  211         bsh = rman_get_bushandle(sc->elcr_res);
  212         for (i = 0; i < ELCR_IOLEN; i++)
  213             sc->saved_elcr[i] = bus_space_read_1(bst, bsh, i);
  214     }
  215 
  216     return (bus_generic_suspend(dev));
  217 }
  218 
  219 static int
  220 isab_resume(device_t dev)
  221 {
  222     struct isab_softc *sc = device_get_softc(dev);
  223     bus_space_tag_t bst;
  224     bus_space_handle_t bsh;
  225     int i;
  226 
  227     /* Restore the ELCR if required. */
  228     if (sc->elcr_res != NULL) {
  229         bst = rman_get_bustag(sc->elcr_res);
  230         bsh = rman_get_bushandle(sc->elcr_res);
  231         for (i = 0; i < ELCR_IOLEN; i++)
  232             bus_space_write_1(bst, bsh, i, sc->saved_elcr[i]);
  233     }
  234 
  235     return (bus_generic_resume(dev));
  236 }

Cache object: 83fc9f859156b705930d9b9ae233d1dd


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