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/i386/isa/isa_compat.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) 1998 Doug Rabson
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  *
   26  * $FreeBSD: releng/5.0/sys/i386/isa/isa_compat.c 78135 2001-06-12 09:40:04Z peter $
   27  */
   28 
   29 #include <sys/param.h>
   30 #include <sys/systm.h>
   31 #include <sys/kernel.h>
   32 #include <sys/bus.h>
   33 #include <sys/malloc.h>
   34 #include <sys/module.h>
   35 #include <machine/bus.h>
   36 #include <sys/rman.h>
   37 
   38 #include <machine/vmparam.h>
   39 #include <vm/vm.h>
   40 #include <vm/pmap.h>
   41 #include <machine/pmap.h>
   42 #include <machine/md_var.h>
   43 
   44 #include <machine/resource.h>
   45 #include <isa/isavar.h>
   46 #include <i386/isa/isa_device.h>
   47 
   48 struct isa_compat_resources {
   49         struct resource *ports;
   50         struct resource *memory;
   51         struct resource *drq;
   52         struct resource *irq;
   53 };
   54 
   55 static void
   56 isa_compat_alloc_resources(device_t dev, struct isa_compat_resources *res)
   57 {
   58         int rid;
   59         u_long start, count;
   60 
   61         if (bus_get_resource(dev, SYS_RES_IOPORT, 0,
   62                              &start, &count) == 0) {
   63                 rid = 0;
   64                 res->ports = bus_alloc_resource(dev, SYS_RES_IOPORT,
   65                                                 &rid, 0ul, ~0ul, 1,
   66                                                 RF_ACTIVE);
   67                 if (res->ports == NULL && bootverbose)
   68                         printf("isa_compat: didn't get ports for %s\n",
   69                                device_get_name(dev));
   70         } else
   71                 res->ports = 0;
   72 
   73         if (bus_get_resource(dev, SYS_RES_MEMORY, 0,
   74                              &start, &count) == 0
   75             && start != 0) {
   76                 rid = 0;
   77                 res->memory = bus_alloc_resource(dev, SYS_RES_MEMORY,
   78                                                  &rid, 0ul, ~0ul, 1,
   79                                                  RF_ACTIVE);
   80                 if (res->memory == NULL && bootverbose)
   81                         printf("isa_compat: didn't get memory for %s\n",
   82                                device_get_name(dev));
   83         } else
   84                 res->memory = 0;
   85 
   86         if (bus_get_resource(dev, SYS_RES_DRQ, 0,
   87                              &start, &count) == 0) {
   88                 rid = 0;
   89                 res->drq = bus_alloc_resource(dev, SYS_RES_DRQ,
   90                                               &rid, 0ul, ~0ul, 1,
   91                                               RF_ACTIVE);
   92                 if (res->drq == NULL && bootverbose)
   93                         printf("isa_compat: didn't get drq for %s\n",
   94                                device_get_name(dev));
   95         } else
   96                 res->drq = 0;
   97 
   98         if (bus_get_resource(dev, SYS_RES_IRQ, 0,
   99                              &start, &count) == 0) {
  100                 rid = 0;
  101                 res->irq = bus_alloc_resource(dev, SYS_RES_IRQ,
  102                                               &rid, 0ul, ~0ul, 1,
  103                                               RF_SHAREABLE | RF_ACTIVE);
  104                 if (res->irq == NULL && bootverbose)
  105                         printf("isa_compat: didn't get irq for %s\n",
  106                                device_get_name(dev));
  107         } else
  108                 res->irq = 0;
  109 }
  110 
  111 static void
  112 isa_compat_release_resources(device_t dev, struct isa_compat_resources *res)
  113 {
  114         if (res->ports) {
  115                 bus_release_resource(dev, SYS_RES_IOPORT, 0, res->ports);
  116                 res->ports = 0;
  117         }
  118         if (res->memory) {
  119                 bus_release_resource(dev, SYS_RES_MEMORY, 0, res->memory);
  120                 res->memory = 0;
  121         }
  122         if (res->drq) {
  123                 bus_release_resource(dev, SYS_RES_DRQ, 0, res->drq);
  124                 res->drq = 0;
  125         }
  126         if (res->irq) {
  127                 bus_release_resource(dev, SYS_RES_IRQ, 0, res->irq);
  128                 res->irq = 0;
  129         }
  130 }
  131 
  132 #define irqmask(x)      ((x) < 0 ? 0 : (1 << (x)))
  133 
  134 static int
  135 isa_compat_probe(device_t dev)
  136 {
  137         struct isa_device *dvp = device_get_softc(dev);
  138         struct isa_compat_resources res;
  139         u_long start, count;
  140 
  141         /* No pnp support */
  142         if (isa_get_vendorid(dev))
  143                 return (ENXIO);
  144 
  145         bzero(&res, sizeof(res));
  146         /*
  147          * Fill in the isa_device fields.
  148          */
  149         dvp->id_driver = device_get_driver(dev)->priv;
  150         if (bus_get_resource(dev, SYS_RES_IOPORT, 0,
  151                              &start, &count) == 0)
  152                 dvp->id_iobase = start;
  153         else
  154                 dvp->id_iobase = -1;
  155         if (bus_get_resource(dev, SYS_RES_IRQ, 0,
  156                              &start, &count) == 0)
  157                 dvp->id_irq = irqmask(start);
  158         else
  159                 dvp->id_irq = 0;
  160         if (bus_get_resource(dev, SYS_RES_DRQ, 0,
  161                              &start, &count) == 0)
  162                 dvp->id_drq = start;
  163         else
  164                 dvp->id_drq = -1;
  165         if (bus_get_resource(dev, SYS_RES_MEMORY,
  166                              0, &start, &count) == 0) {
  167                 dvp->id_maddr = (void *)(uintptr_t)start;
  168                 dvp->id_msize = count;
  169         } else {
  170                 dvp->id_maddr = NULL;
  171                 dvp->id_msize = 0;
  172         }
  173         dvp->id_unit = device_get_unit(dev);
  174         dvp->id_flags = device_get_flags(dev);
  175         dvp->id_enabled = device_is_enabled(dev);       /* XXX unused */
  176         dvp->id_device = dev;
  177 
  178         /*
  179          * Do the wrapped probe.
  180          */
  181         if (dvp->id_driver->probe) {
  182                 int portsize;
  183                 void *maddr;
  184                 struct isa_device old;
  185 
  186                 isa_compat_alloc_resources(dev, &res);
  187                 if (res.memory)
  188                         maddr = rman_get_virtual(res.memory);
  189                 else
  190                         maddr = 0;
  191                 dvp->id_maddr = maddr;
  192                 old = *dvp;
  193                 portsize = dvp->id_driver->probe(dvp);
  194                 isa_compat_release_resources(dev, &res);
  195                 if (portsize != 0) {
  196                         if (portsize > 0 || dvp->id_iobase != old.id_iobase)
  197                                 bus_set_resource(dev, SYS_RES_IOPORT,
  198                                                  0, dvp->id_iobase, portsize);
  199                         if (dvp->id_irq != old.id_irq)
  200                                 bus_set_resource(dev, SYS_RES_IRQ, 0,
  201                                                  ffs(dvp->id_irq) - 1, 1);
  202                         if (dvp->id_drq != old.id_drq)
  203                                 bus_set_resource(dev, SYS_RES_DRQ, 0,
  204                                                  dvp->id_drq, 1);
  205                         if (dvp->id_maddr != old.id_maddr
  206                             || dvp->id_msize != old.id_msize) {
  207                                 maddr = dvp->id_maddr;
  208                                 if (maddr != NULL)
  209                                         bus_set_resource(dev,
  210                                                          SYS_RES_MEMORY,
  211                                                          0,
  212                                                          kvtop(maddr),
  213                                                          dvp->id_msize);
  214                                 else
  215                                         bus_delete_resource(dev,
  216                                                             SYS_RES_MEMORY,
  217                                                             0);
  218                         }
  219                         return 0;
  220                 }
  221         }
  222         return ENXIO;
  223 }
  224 
  225 static int
  226 isa_compat_attach(device_t dev)
  227 {
  228         struct isa_device *dvp = device_get_softc(dev);
  229         struct isa_compat_resources res;
  230         int error;
  231 
  232         bzero(&res, sizeof(res));
  233         isa_compat_alloc_resources(dev, &res);
  234         if (dvp->id_driver->attach)
  235                 dvp->id_driver->attach(dvp);
  236         if (res.irq && dvp->id_irq && dvp->id_intr) {
  237                 void *ih;
  238 
  239                 error = BUS_SETUP_INTR(device_get_parent(dev), dev,
  240                                        res.irq, dvp->id_driver->intrflags,
  241                                        dvp->id_intr,
  242                                        (void *)(uintptr_t)dvp->id_unit,
  243                                        &ih);
  244                 if (error)
  245                         printf("isa_compat_attach: failed to setup intr: %d\n",
  246                                error);
  247         }
  248         device_printf(dev, "driver is using old-style compatibility shims\n");
  249         return 0;
  250 }
  251 
  252 static device_method_t isa_compat_methods[] = {
  253         /* Device interface */
  254         DEVMETHOD(device_probe,         isa_compat_probe),
  255         DEVMETHOD(device_attach,        isa_compat_attach),
  256 
  257         { 0, 0 }
  258 };
  259 
  260 /*
  261  * Create a new style driver around each old isa driver.
  262  */
  263 int
  264 compat_isa_handler(module_t mod, int type, void *data)
  265 {
  266         struct isa_driver *id = (struct isa_driver *)data;
  267         driver_t *driver;
  268         devclass_t isa_devclass = devclass_find("isa");
  269 
  270         switch (type) {
  271         case MOD_LOAD:
  272                 driver = malloc(sizeof(driver_t), M_DEVBUF, M_NOWAIT | M_ZERO);
  273                 if (!driver)
  274                         return ENOMEM;
  275                 driver->name = id->name;
  276                 driver->methods = isa_compat_methods;
  277                 driver->size = sizeof(struct isa_device);
  278                 driver->priv = id;
  279                 if (id->sensitive_hw) {
  280 #if 0
  281                         resource_set_int(id->name, -1, "sensitive", 1);
  282 #else
  283                         printf("WARNING: isa driver %s is sensitive, but cannot set it!\n",
  284                             driver->name);
  285 #endif
  286                 }
  287                 devclass_add_driver(isa_devclass, driver);
  288                 break;
  289         case MOD_UNLOAD:
  290                 printf("%s: module unload not supported!\n", id->name);
  291                 return EOPNOTSUPP;
  292         default:
  293                 break;
  294         }
  295         return 0;
  296 }

Cache object: 9f71f0fb3aa6230595a2acde3afb4899


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