linux/drivers/pnp/system.c
<<
>>
Prefs
   1/*
   2 * system.c - a driver for reserving pnp system resources
   3 *
   4 * Some code is based on pnpbios_core.c
   5 * Copyright 2002 Adam Belay <ambx1@neo.rr.com>
   6 * (c) Copyright 2007 Hewlett-Packard Development Company, L.P.
   7 *      Bjorn Helgaas <bjorn.helgaas@hp.com>
   8 */
   9
  10#include <linux/pnp.h>
  11#include <linux/device.h>
  12#include <linux/init.h>
  13#include <linux/slab.h>
  14#include <linux/kernel.h>
  15#include <linux/ioport.h>
  16
  17static const struct pnp_device_id pnp_dev_table[] = {
  18        /* General ID for reserving resources */
  19        {"PNP0c02", 0},
  20        /* memory controller */
  21        {"PNP0c01", 0},
  22        {"", 0}
  23};
  24
  25static void reserve_range(struct pnp_dev *dev, struct resource *r, int port)
  26{
  27        char *regionid;
  28        const char *pnpid = dev_name(&dev->dev);
  29        resource_size_t start = r->start, end = r->end;
  30        struct resource *res;
  31
  32        regionid = kmalloc(16, GFP_KERNEL);
  33        if (!regionid)
  34                return;
  35
  36        snprintf(regionid, 16, "pnp %s", pnpid);
  37        if (port)
  38                res = request_region(start, end - start + 1, regionid);
  39        else
  40                res = request_mem_region(start, end - start + 1, regionid);
  41        if (res)
  42                res->flags &= ~IORESOURCE_BUSY;
  43        else
  44                kfree(regionid);
  45
  46        /*
  47         * Failures at this point are usually harmless. pci quirks for
  48         * example do reserve stuff they know about too, so we may well
  49         * have double reservations.
  50         */
  51        dev_info(&dev->dev, "%pR %s reserved\n", r,
  52                 res ? "has been" : "could not be");
  53}
  54
  55static void reserve_resources_of_dev(struct pnp_dev *dev)
  56{
  57        struct resource *res;
  58        int i;
  59
  60        for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_IO, i)); i++) {
  61                if (res->flags & IORESOURCE_DISABLED)
  62                        continue;
  63                if (res->start == 0)
  64                        continue;       /* disabled */
  65                if (res->start < 0x100)
  66                        /*
  67                         * Below 0x100 is only standard PC hardware
  68                         * (pics, kbd, timer, dma, ...)
  69                         * We should not get resource conflicts there,
  70                         * and the kernel reserves these anyway
  71                         * (see arch/i386/kernel/setup.c).
  72                         * So, do nothing
  73                         */
  74                        continue;
  75                if (res->end < res->start)
  76                        continue;       /* invalid */
  77
  78                reserve_range(dev, res, 1);
  79        }
  80
  81        for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_MEM, i)); i++) {
  82                if (res->flags & IORESOURCE_DISABLED)
  83                        continue;
  84
  85                reserve_range(dev, res, 0);
  86        }
  87}
  88
  89static int system_pnp_probe(struct pnp_dev *dev,
  90                            const struct pnp_device_id *dev_id)
  91{
  92        reserve_resources_of_dev(dev);
  93        return 0;
  94}
  95
  96static struct pnp_driver system_pnp_driver = {
  97        .name     = "system",
  98        .id_table = pnp_dev_table,
  99        .flags    = PNP_DRIVER_RES_DO_NOT_CHANGE,
 100        .probe    = system_pnp_probe,
 101};
 102
 103static int __init pnp_system_init(void)
 104{
 105        return pnp_register_driver(&system_pnp_driver);
 106}
 107
 108/**
 109 * Reserve motherboard resources after PCI claim BARs,
 110 * but before PCI assign resources for uninitialized PCI devices
 111 */
 112fs_initcall(pnp_system_init);
 113