| 1 | |
| 2 | |
| 3 | * core.c - contains all core device and protocol registration functions
|
| 4 | *
|
| 5 | * Copyright 2002 Adam Belay <[email protected]>
|
| 6 |
|
| 7 |
|
| 8 | #include <linux/pnp.h>
|
| 9 | #include <linux/types.h>
|
| 10 | #include <linux/list.h>
|
| 11 | #include <linux/device.h>
|
| 12 | #include <linux/module.h>
|
| 13 | #include <linux/mutex.h>
|
| 14 | #include <linux/init.h>
|
| 15 | #include <linux/string.h>
|
| 16 | #include <linux/slab.h>
|
| 17 | #include <linux/errno.h>
|
| 18 | #include <linux/dma-mapping.h>
|
| 19 |
|
| 20 | #include "base.h"
|
| 21 |
|
| 22 | static LIST_HEAD(pnp_protocols);
|
| 23 | LIST_HEAD(pnp_global);
|
| 24 | DEFINE_MUTEX(pnp_lock);
|
| 25 |
|
| 26 | |
| 27 | * ACPI or PNPBIOS should tell us about all platform devices, so we can
|
| 28 | * skip some blind probes. ISAPNP typically enumerates only plug-in ISA
|
| 29 | * devices, not built-in things like COM ports.
|
| 30 |
|
| 31 | int pnp_platform_devices;
|
| 32 | EXPORT_SYMBOL(pnp_platform_devices);
|
| 33 |
|
| 34 | static void pnp_remove_protocol(struct pnp_protocol *protocol)
|
| 35 | {
|
| 36 | mutex_lock(&pnp_lock);
|
| 37 | list_del(&protocol->protocol_list);
|
| 38 | mutex_unlock(&pnp_lock);
|
| 39 | }
|
| 40 |
|
| 41 | |
| 42 | * pnp_register_protocol - adds a pnp protocol to the pnp layer
|
| 43 | * @protocol: pointer to the corresponding pnp_protocol structure
|
| 44 | *
|
| 45 | * Ex protocols: ISAPNP, PNPBIOS, etc
|
| 46 |
|
| 47 | int pnp_register_protocol(struct pnp_protocol *protocol)
|
| 48 | {
|
| 49 | struct list_head *pos;
|
| 50 | int nodenum, ret;
|
| 51 |
|
| 52 | INIT_LIST_HEAD(&protocol->devices);
|
| 53 | INIT_LIST_HEAD(&protocol->cards);
|
| 54 | nodenum = 0;
|
| 55 |
|
| 56 | mutex_lock(&pnp_lock);
|
| 57 |
|
| 58 |
|
| 59 | list_for_each(pos, &pnp_protocols) {
|
| 60 | struct pnp_protocol *cur = to_pnp_protocol(pos);
|
| 61 | if (cur->number == nodenum) {
|
| 62 | pos = &pnp_protocols;
|
| 63 | nodenum++;
|
| 64 | }
|
| 65 | }
|
| 66 |
|
| 67 | protocol->number = nodenum;
|
| 68 | dev_set_name(&protocol->dev, "pnp%d", nodenum);
|
| 69 |
|
| 70 | list_add_tail(&protocol->protocol_list, &pnp_protocols);
|
| 71 |
|
| 72 | mutex_unlock(&pnp_lock);
|
| 73 |
|
| 74 | ret = device_register(&protocol->dev);
|
| 75 | if (ret)
|
| 76 | pnp_remove_protocol(protocol);
|
| 77 |
|
| 78 | return ret;
|
| 79 | }
|
| 80 |
|
| 81 | static void pnp_free_ids(struct pnp_dev *dev)
|
| 82 | {
|
| 83 | struct pnp_id *id;
|
| 84 | struct pnp_id *next;
|
| 85 |
|
| 86 | id = dev->id;
|
| 87 | while (id) {
|
| 88 | next = id->next;
|
| 89 | kfree(id);
|
| 90 | id = next;
|
| 91 | }
|
| 92 | }
|
| 93 |
|
| 94 | void pnp_free_resource(struct pnp_resource *pnp_res)
|
| 95 | {
|
| 96 | list_del(&pnp_res->list);
|
| 97 | kfree(pnp_res);
|
| 98 | }
|
| 99 |
|
| 100 | void pnp_free_resources(struct pnp_dev *dev)
|
| 101 | {
|
| 102 | struct pnp_resource *pnp_res, *tmp;
|
| 103 |
|
| 104 | list_for_each_entry_safe(pnp_res, tmp, &dev->resources, list) {
|
| 105 | pnp_free_resource(pnp_res);
|
| 106 | }
|
| 107 | }
|
| 108 |
|
| 109 | static void pnp_release_device(struct device *dmdev)
|
| 110 | {
|
| 111 | struct pnp_dev *dev = to_pnp_dev(dmdev);
|
| 112 |
|
| 113 | pnp_free_ids(dev);
|
| 114 | pnp_free_resources(dev);
|
| 115 | pnp_free_options(dev);
|
| 116 | kfree(dev);
|
| 117 | }
|
| 118 |
|
| 119 | struct pnp_dev *pnp_alloc_dev(struct pnp_protocol *protocol, int id,
|
| 120 | const char *pnpid)
|
| 121 | {
|
| 122 | struct pnp_dev *dev;
|
| 123 | struct pnp_id *dev_id;
|
| 124 |
|
| 125 | dev = kzalloc_obj(struct pnp_dev);
|
| 126 | if (!dev)
|
| 127 | return NULL;
|
| 128 |
|
| 129 | INIT_LIST_HEAD(&dev->resources);
|
| 130 | INIT_LIST_HEAD(&dev->options);
|
| 131 | dev->protocol = protocol;
|
| 132 | dev->number = id;
|
| 133 | dev->dma_mask = DMA_BIT_MASK(24);
|
| 134 |
|
| 135 | dev->dev.parent = &dev->protocol->dev;
|
| 136 | dev->dev.bus = &pnp_bus_type;
|
| 137 | dev->dev.dma_mask = &dev->dma_mask;
|
| 138 | dev->dev.coherent_dma_mask = dev->dma_mask;
|
| 139 | dev->dev.release = &pnp_release_device;
|
| 140 |
|
| 141 | dev_id = pnp_add_id(dev, pnpid);
|
| 142 | if (!dev_id) {
|
| 143 | kfree(dev);
|
| 144 | return NULL;
|
| 145 | }
|
| 146 |
|
| 147 | dev_set_name(&dev->dev, "%02x:%02x", dev->protocol->number, dev->number);
|
| 148 |
|
| 149 | return dev;
|
| 150 | }
|
| 151 |
|
| 152 | static void pnp_delist_device(struct pnp_dev *dev)
|
| 153 | {
|
| 154 | mutex_lock(&pnp_lock);
|
| 155 | list_del(&dev->global_list);
|
| 156 | list_del(&dev->protocol_list);
|
| 157 | mutex_unlock(&pnp_lock);
|
| 158 | }
|
| 159 |
|
| 160 | int __pnp_add_device(struct pnp_dev *dev)
|
| 161 | {
|
| 162 | int ret;
|
| 163 |
|
| 164 | pnp_fixup_device(dev);
|
| 165 | dev->status = PNP_READY;
|
| 166 |
|
| 167 | mutex_lock(&pnp_lock);
|
| 168 |
|
| 169 | list_add_tail(&dev->global_list, &pnp_global);
|
| 170 | list_add_tail(&dev->protocol_list, &dev->protocol->devices);
|
| 171 |
|
| 172 | mutex_unlock(&pnp_lock);
|
| 173 |
|
| 174 | ret = device_register(&dev->dev);
|
| 175 | if (ret)
|
| 176 | pnp_delist_device(dev);
|
| 177 | else if (dev->protocol->can_wakeup)
|
| 178 | device_set_wakeup_capable(&dev->dev,
|
| 179 | dev->protocol->can_wakeup(dev));
|
| 180 |
|
| 181 | return ret;
|
| 182 | }
|
| 183 |
|
| 184 | |
| 185 | * pnp_add_device - adds a pnp device to the pnp layer
|
| 186 | * @dev: pointer to dev to add
|
| 187 | *
|
| 188 | * adds to driver model, name database, fixups, interface, etc.
|
| 189 |
|
| 190 | int pnp_add_device(struct pnp_dev *dev)
|
| 191 | {
|
| 192 | int ret;
|
| 193 | char buf[128];
|
| 194 | int len = 0;
|
| 195 | struct pnp_id *id;
|
| 196 |
|
| 197 | if (dev->card)
|
| 198 | return -EINVAL;
|
| 199 |
|
| 200 | ret = __pnp_add_device(dev);
|
| 201 | if (ret)
|
| 202 | return ret;
|
| 203 |
|
| 204 | buf[0] = '\0';
|
| 205 | for (id = dev->id; id; id = id->next)
|
| 206 | len += scnprintf(buf + len, sizeof(buf) - len, " %s", id->id);
|
| 207 |
|
| 208 | dev_dbg(&dev->dev, "%s device, IDs%s (%s)\n", dev->protocol->name, buf,
|
| 209 | dev->active ? "active" : "disabled");
|
| 210 | return 0;
|
| 211 | }
|
| 212 |
|
| 213 | static int __init pnp_init(void)
|
| 214 | {
|
| 215 | return bus_register(&pnp_bus_type);
|
| 216 | }
|
| 217 |
|
| 218 | subsys_initcall(pnp_init);
|
| 219 |
|
| 220 | int pnp_debug;
|
| 221 |
|
| 222 | #if defined(CONFIG_PNP_DEBUG_MESSAGES)
|
| 223 | module_param_named(debug, pnp_debug, int, 0644);
|
| 224 | #endif
|