linux/drivers/base/isa.c
<<
>>
Prefs
   1/*
   2 * ISA bus.
   3 */
   4
   5#include <linux/device.h>
   6#include <linux/kernel.h>
   7#include <linux/slab.h>
   8#include <linux/module.h>
   9#include <linux/init.h>
  10#include <linux/dma-mapping.h>
  11#include <linux/isa.h>
  12
  13static struct device isa_bus = {
  14        .init_name      = "isa"
  15};
  16
  17struct isa_dev {
  18        struct device dev;
  19        struct device *next;
  20        unsigned int id;
  21};
  22
  23#define to_isa_dev(x) container_of((x), struct isa_dev, dev)
  24
  25static int isa_bus_match(struct device *dev, struct device_driver *driver)
  26{
  27        struct isa_driver *isa_driver = to_isa_driver(driver);
  28
  29        if (dev->platform_data == isa_driver) {
  30                if (!isa_driver->match ||
  31                        isa_driver->match(dev, to_isa_dev(dev)->id))
  32                        return 1;
  33                dev->platform_data = NULL;
  34        }
  35        return 0;
  36}
  37
  38static int isa_bus_probe(struct device *dev)
  39{
  40        struct isa_driver *isa_driver = dev->platform_data;
  41
  42        if (isa_driver->probe)
  43                return isa_driver->probe(dev, to_isa_dev(dev)->id);
  44
  45        return 0;
  46}
  47
  48static int isa_bus_remove(struct device *dev)
  49{
  50        struct isa_driver *isa_driver = dev->platform_data;
  51
  52        if (isa_driver->remove)
  53                return isa_driver->remove(dev, to_isa_dev(dev)->id);
  54
  55        return 0;
  56}
  57
  58static void isa_bus_shutdown(struct device *dev)
  59{
  60        struct isa_driver *isa_driver = dev->platform_data;
  61
  62        if (isa_driver->shutdown)
  63                isa_driver->shutdown(dev, to_isa_dev(dev)->id);
  64}
  65
  66static int isa_bus_suspend(struct device *dev, pm_message_t state)
  67{
  68        struct isa_driver *isa_driver = dev->platform_data;
  69
  70        if (isa_driver->suspend)
  71                return isa_driver->suspend(dev, to_isa_dev(dev)->id, state);
  72
  73        return 0;
  74}
  75
  76static int isa_bus_resume(struct device *dev)
  77{
  78        struct isa_driver *isa_driver = dev->platform_data;
  79
  80        if (isa_driver->resume)
  81                return isa_driver->resume(dev, to_isa_dev(dev)->id);
  82
  83        return 0;
  84}
  85
  86static struct bus_type isa_bus_type = {
  87        .name           = "isa",
  88        .match          = isa_bus_match,
  89        .probe          = isa_bus_probe,
  90        .remove         = isa_bus_remove,
  91        .shutdown       = isa_bus_shutdown,
  92        .suspend        = isa_bus_suspend,
  93        .resume         = isa_bus_resume
  94};
  95
  96static void isa_dev_release(struct device *dev)
  97{
  98        kfree(to_isa_dev(dev));
  99}
 100
 101void isa_unregister_driver(struct isa_driver *isa_driver)
 102{
 103        struct device *dev = isa_driver->devices;
 104
 105        while (dev) {
 106                struct device *tmp = to_isa_dev(dev)->next;
 107                device_unregister(dev);
 108                dev = tmp;
 109        }
 110        driver_unregister(&isa_driver->driver);
 111}
 112EXPORT_SYMBOL_GPL(isa_unregister_driver);
 113
 114int isa_register_driver(struct isa_driver *isa_driver, unsigned int ndev)
 115{
 116        int error;
 117        unsigned int id;
 118
 119        isa_driver->driver.bus  = &isa_bus_type;
 120        isa_driver->devices     = NULL;
 121
 122        error = driver_register(&isa_driver->driver);
 123        if (error)
 124                return error;
 125
 126        for (id = 0; id < ndev; id++) {
 127                struct isa_dev *isa_dev;
 128
 129                isa_dev = kzalloc(sizeof *isa_dev, GFP_KERNEL);
 130                if (!isa_dev) {
 131                        error = -ENOMEM;
 132                        break;
 133                }
 134
 135                isa_dev->dev.parent     = &isa_bus;
 136                isa_dev->dev.bus        = &isa_bus_type;
 137
 138                dev_set_name(&isa_dev->dev, "%s.%u",
 139                             isa_driver->driver.name, id);
 140                isa_dev->dev.platform_data      = isa_driver;
 141                isa_dev->dev.release            = isa_dev_release;
 142                isa_dev->id                     = id;
 143
 144                isa_dev->dev.coherent_dma_mask = DMA_BIT_MASK(24);
 145                isa_dev->dev.dma_mask = &isa_dev->dev.coherent_dma_mask;
 146
 147                error = device_register(&isa_dev->dev);
 148                if (error) {
 149                        put_device(&isa_dev->dev);
 150                        break;
 151                }
 152
 153                if (isa_dev->dev.platform_data) {
 154                        isa_dev->next = isa_driver->devices;
 155                        isa_driver->devices = &isa_dev->dev;
 156                } else
 157                        device_unregister(&isa_dev->dev);
 158        }
 159
 160        if (!error && !isa_driver->devices)
 161                error = -ENODEV;
 162
 163        if (error)
 164                isa_unregister_driver(isa_driver);
 165
 166        return error;
 167}
 168EXPORT_SYMBOL_GPL(isa_register_driver);
 169
 170static int __init isa_bus_init(void)
 171{
 172        int error;
 173
 174        error = bus_register(&isa_bus_type);
 175        if (!error) {
 176                error = device_register(&isa_bus);
 177                if (error)
 178                        bus_unregister(&isa_bus_type);
 179        }
 180        return error;
 181}
 182
 183device_initcall(isa_bus_init);
 184