Blame view
drivers/acpi/container.c
6.88 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
/* * acpi_container.c - ACPI Generic Container Driver * ($Revision: ) * * Copyright (C) 2004 Anil S Keshavamurthy (anil.s.keshavamurthy@intel.com) * Copyright (C) 2004 Keiichiro Tokunaga (tokunaga.keiich@jp.fujitsu.com) * Copyright (C) 2004 Motoyuki Ito (motoyuki@soft.fujitsu.com) * Copyright (C) 2004 Intel Corp. * Copyright (C) 2004 FUJITSU LIMITED * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> |
5a0e3ad6a include cleanup: ... |
32 |
#include <linux/slab.h> |
1da177e4c Linux-2.6.12-rc2 |
33 34 35 36 37 |
#include <linux/types.h> #include <linux/acpi.h> #include <acpi/acpi_bus.h> #include <acpi/acpi_drivers.h> #include <acpi/container.h> |
a192a9580 ACPI: Move defini... |
38 |
#define PREFIX "ACPI: " |
1da177e4c Linux-2.6.12-rc2 |
39 40 41 42 43 |
#define ACPI_CONTAINER_DEVICE_NAME "ACPI container device" #define ACPI_CONTAINER_CLASS "container" #define INSTALL_NOTIFY_HANDLER 1 #define UNINSTALL_NOTIFY_HANDLER 2 |
1da177e4c Linux-2.6.12-rc2 |
44 |
#define _COMPONENT ACPI_CONTAINER_COMPONENT |
f52fd66d2 ACPI: clean up AC... |
45 |
ACPI_MODULE_NAME("container"); |
1da177e4c Linux-2.6.12-rc2 |
46 |
|
f52fd66d2 ACPI: clean up AC... |
47 |
MODULE_AUTHOR("Anil S Keshavamurthy"); |
7cda93e00 ACPI: delete extr... |
48 |
MODULE_DESCRIPTION("ACPI container driver"); |
1da177e4c Linux-2.6.12-rc2 |
49 |
MODULE_LICENSE("GPL"); |
1da177e4c Linux-2.6.12-rc2 |
50 51 |
static int acpi_container_add(struct acpi_device *device); static int acpi_container_remove(struct acpi_device *device, int type); |
1ba90e3a8 ACPI: autoload mo... |
52 53 54 55 56 57 58 |
static const struct acpi_device_id container_device_ids[] = { {"ACPI0004", 0}, {"PNP0A05", 0}, {"PNP0A06", 0}, {"", 0}, }; MODULE_DEVICE_TABLE(acpi, container_device_ids); |
1da177e4c Linux-2.6.12-rc2 |
59 |
static struct acpi_driver acpi_container_driver = { |
c2b6705b7 ACPI: fix acpi_dr... |
60 |
.name = "container", |
4be44fcd3 [ACPI] Lindent al... |
61 |
.class = ACPI_CONTAINER_CLASS, |
1ba90e3a8 ACPI: autoload mo... |
62 |
.ids = container_device_ids, |
4be44fcd3 [ACPI] Lindent al... |
63 64 65 66 |
.ops = { .add = acpi_container_add, .remove = acpi_container_remove, }, |
1da177e4c Linux-2.6.12-rc2 |
67 |
}; |
1da177e4c Linux-2.6.12-rc2 |
68 |
/*******************************************************************/ |
4be44fcd3 [ACPI] Lindent al... |
69 |
static int is_device_present(acpi_handle handle) |
1da177e4c Linux-2.6.12-rc2 |
70 |
{ |
4be44fcd3 [ACPI] Lindent al... |
71 72 |
acpi_handle temp; acpi_status status; |
27663c585 ACPI: Change acpi... |
73 |
unsigned long long sta; |
1da177e4c Linux-2.6.12-rc2 |
74 |
|
1da177e4c Linux-2.6.12-rc2 |
75 76 77 |
status = acpi_get_handle(handle, "_STA", &temp); if (ACPI_FAILURE(status)) |
a0bd4ac49 ACPI: Remove dupl... |
78 |
return 1; /* _STA not found, assume device present */ |
1da177e4c Linux-2.6.12-rc2 |
79 80 81 |
status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); if (ACPI_FAILURE(status)) |
d550d98d3 ACPI: delete trac... |
82 |
return 0; /* Firmware error */ |
1da177e4c Linux-2.6.12-rc2 |
83 |
|
a0bd4ac49 ACPI: Remove dupl... |
84 |
return ((sta & ACPI_STA_DEVICE_PRESENT) == ACPI_STA_DEVICE_PRESENT); |
1da177e4c Linux-2.6.12-rc2 |
85 86 87 |
} /*******************************************************************/ |
4be44fcd3 [ACPI] Lindent al... |
88 |
static int acpi_container_add(struct acpi_device *device) |
1da177e4c Linux-2.6.12-rc2 |
89 90 |
{ struct acpi_container *container; |
1da177e4c Linux-2.6.12-rc2 |
91 92 |
if (!device) { |
6468463ab ACPI: un-export A... |
93 94 |
printk(KERN_ERR PREFIX "device is NULL "); |
d550d98d3 ACPI: delete trac... |
95 |
return -EINVAL; |
1da177e4c Linux-2.6.12-rc2 |
96 |
} |
36bcbec7c ACPI: replace kma... |
97 |
container = kzalloc(sizeof(struct acpi_container), GFP_KERNEL); |
4be44fcd3 [ACPI] Lindent al... |
98 |
if (!container) |
d550d98d3 ACPI: delete trac... |
99 |
return -ENOMEM; |
4be44fcd3 [ACPI] Lindent al... |
100 |
|
1da177e4c Linux-2.6.12-rc2 |
101 102 103 |
container->handle = device->handle; strcpy(acpi_device_name(device), ACPI_CONTAINER_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_CONTAINER_CLASS); |
db89b4f0d ACPI: catch calls... |
104 |
device->driver_data = container; |
1da177e4c Linux-2.6.12-rc2 |
105 |
|
4be44fcd3 [ACPI] Lindent al... |
106 107 108 |
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device <%s> bid <%s> ", acpi_device_name(device), acpi_device_bid(device))); |
1da177e4c Linux-2.6.12-rc2 |
109 |
|
d550d98d3 ACPI: delete trac... |
110 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
111 |
} |
4be44fcd3 [ACPI] Lindent al... |
112 |
static int acpi_container_remove(struct acpi_device *device, int type) |
1da177e4c Linux-2.6.12-rc2 |
113 |
{ |
4be44fcd3 [ACPI] Lindent al... |
114 115 |
acpi_status status = AE_OK; struct acpi_container *pc = NULL; |
1da177e4c Linux-2.6.12-rc2 |
116 |
|
50dd09697 ACPI: Remove unne... |
117 |
pc = acpi_driver_data(device); |
6044ec888 [PATCH] kfree cle... |
118 |
kfree(pc); |
1da177e4c Linux-2.6.12-rc2 |
119 120 |
return status; } |
4be44fcd3 [ACPI] Lindent al... |
121 |
static int container_device_add(struct acpi_device **device, acpi_handle handle) |
1da177e4c Linux-2.6.12-rc2 |
122 123 124 125 |
{ acpi_handle phandle; struct acpi_device *pdev; int result; |
1da177e4c Linux-2.6.12-rc2 |
126 127 |
if (acpi_get_parent(handle, &phandle)) { |
d550d98d3 ACPI: delete trac... |
128 |
return -ENODEV; |
1da177e4c Linux-2.6.12-rc2 |
129 130 131 |
} if (acpi_bus_get_device(phandle, &pdev)) { |
d550d98d3 ACPI: delete trac... |
132 |
return -ENODEV; |
1da177e4c Linux-2.6.12-rc2 |
133 134 135 |
} if (acpi_bus_add(device, pdev, handle, ACPI_BUS_TYPE_DEVICE)) { |
d550d98d3 ACPI: delete trac... |
136 |
return -ENODEV; |
1da177e4c Linux-2.6.12-rc2 |
137 |
} |
3fb02738b [PATCH] acpi brid... |
138 |
result = acpi_bus_start(*device); |
1da177e4c Linux-2.6.12-rc2 |
139 |
|
d550d98d3 ACPI: delete trac... |
140 |
return result; |
1da177e4c Linux-2.6.12-rc2 |
141 |
} |
4be44fcd3 [ACPI] Lindent al... |
142 |
static void container_notify_cb(acpi_handle handle, u32 type, void *context) |
1da177e4c Linux-2.6.12-rc2 |
143 |
{ |
4be44fcd3 [ACPI] Lindent al... |
144 |
struct acpi_device *device = NULL; |
1da177e4c Linux-2.6.12-rc2 |
145 146 147 |
int result; int present; acpi_status status; |
1da177e4c Linux-2.6.12-rc2 |
148 149 |
present = is_device_present(handle); |
4be44fcd3 [ACPI] Lindent al... |
150 |
|
1da177e4c Linux-2.6.12-rc2 |
151 152 153 154 |
switch (type) { case ACPI_NOTIFY_BUS_CHECK: /* Fall through */ case ACPI_NOTIFY_DEVICE_CHECK: |
4d9391557 ACPI: add missing... |
155 156 |
printk(KERN_WARNING "Container driver received %s event ", |
4be44fcd3 [ACPI] Lindent al... |
157 158 |
(type == ACPI_NOTIFY_BUS_CHECK) ? "ACPI_NOTIFY_BUS_CHECK" : "ACPI_NOTIFY_DEVICE_CHECK"); |
1da177e4c Linux-2.6.12-rc2 |
159 160 161 162 163 |
status = acpi_bus_get_device(handle, &device); if (present) { if (ACPI_FAILURE(status) || !device) { result = container_device_add(&device, handle); if (!result) |
f883d9db0 ACPI: convert to ... |
164 |
kobject_uevent(&device->dev.kobj, |
312c004d3 [PATCH] driver co... |
165 |
KOBJ_ONLINE); |
1da177e4c Linux-2.6.12-rc2 |
166 |
else |
4d9391557 ACPI: add missing... |
167 168 169 |
printk(KERN_WARNING "Failed to add container "); |
1da177e4c Linux-2.6.12-rc2 |
170 171 172 173 |
} } else { if (ACPI_SUCCESS(status)) { /* device exist and this is a remove request */ |
f883d9db0 ACPI: convert to ... |
174 |
kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE); |
1da177e4c Linux-2.6.12-rc2 |
175 176 177 178 179 |
} } break; case ACPI_NOTIFY_EJECT_REQUEST: if (!acpi_bus_get_device(handle, &device) && device) { |
f883d9db0 ACPI: convert to ... |
180 |
kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE); |
1da177e4c Linux-2.6.12-rc2 |
181 182 183 184 185 |
} break; default: break; } |
d550d98d3 ACPI: delete trac... |
186 |
return; |
1da177e4c Linux-2.6.12-rc2 |
187 188 189 190 |
} static acpi_status container_walk_namespace_cb(acpi_handle handle, |
4be44fcd3 [ACPI] Lindent al... |
191 |
u32 lvl, void *context, void **rv) |
1da177e4c Linux-2.6.12-rc2 |
192 |
{ |
4be44fcd3 [ACPI] Lindent al... |
193 |
char *hid = NULL; |
4be44fcd3 [ACPI] Lindent al... |
194 195 196 |
struct acpi_device_info *info; acpi_status status; int *action = context; |
1da177e4c Linux-2.6.12-rc2 |
197 |
|
15b8dd53f ACPICA: Major upd... |
198 199 |
status = acpi_get_object_info(handle, &info); if (ACPI_FAILURE(status)) { |
d550d98d3 ACPI: delete trac... |
200 |
return AE_OK; |
1da177e4c Linux-2.6.12-rc2 |
201 |
} |
1da177e4c Linux-2.6.12-rc2 |
202 |
if (info->valid & ACPI_VALID_HID) |
15b8dd53f ACPICA: Major upd... |
203 |
hid = info->hardware_id.string; |
1da177e4c Linux-2.6.12-rc2 |
204 205 206 207 208 209 |
if (hid == NULL) { goto end; } if (strcmp(hid, "ACPI0004") && strcmp(hid, "PNP0A05") && |
4be44fcd3 [ACPI] Lindent al... |
210 |
strcmp(hid, "PNP0A06")) { |
1da177e4c Linux-2.6.12-rc2 |
211 212 |
goto end; } |
4be44fcd3 [ACPI] Lindent al... |
213 |
switch (*action) { |
1da177e4c Linux-2.6.12-rc2 |
214 215 |
case INSTALL_NOTIFY_HANDLER: acpi_install_notify_handler(handle, |
4be44fcd3 [ACPI] Lindent al... |
216 217 |
ACPI_SYSTEM_NOTIFY, container_notify_cb, NULL); |
1da177e4c Linux-2.6.12-rc2 |
218 219 220 |
break; case UNINSTALL_NOTIFY_HANDLER: acpi_remove_notify_handler(handle, |
4be44fcd3 [ACPI] Lindent al... |
221 222 |
ACPI_SYSTEM_NOTIFY, container_notify_cb); |
1da177e4c Linux-2.6.12-rc2 |
223 224 225 226 |
break; default: break; } |
4be44fcd3 [ACPI] Lindent al... |
227 |
end: |
15b8dd53f ACPICA: Major upd... |
228 |
kfree(info); |
1da177e4c Linux-2.6.12-rc2 |
229 |
|
d550d98d3 ACPI: delete trac... |
230 |
return AE_OK; |
1da177e4c Linux-2.6.12-rc2 |
231 |
} |
4be44fcd3 [ACPI] Lindent al... |
232 |
static int __init acpi_container_init(void) |
1da177e4c Linux-2.6.12-rc2 |
233 |
{ |
4be44fcd3 [ACPI] Lindent al... |
234 235 |
int result = 0; int action = INSTALL_NOTIFY_HANDLER; |
1da177e4c Linux-2.6.12-rc2 |
236 237 238 |
result = acpi_bus_register_driver(&acpi_container_driver); if (result < 0) { |
4be44fcd3 [ACPI] Lindent al... |
239 |
return (result); |
1da177e4c Linux-2.6.12-rc2 |
240 241 242 243 |
} /* register notify handler to every container device */ acpi_walk_namespace(ACPI_TYPE_DEVICE, |
4be44fcd3 [ACPI] Lindent al... |
244 245 |
ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, |
2263576cf ACPICA: Add post-... |
246 |
container_walk_namespace_cb, NULL, &action, NULL); |
1da177e4c Linux-2.6.12-rc2 |
247 |
|
4be44fcd3 [ACPI] Lindent al... |
248 |
return (0); |
1da177e4c Linux-2.6.12-rc2 |
249 |
} |
4be44fcd3 [ACPI] Lindent al... |
250 |
static void __exit acpi_container_exit(void) |
1da177e4c Linux-2.6.12-rc2 |
251 |
{ |
4be44fcd3 [ACPI] Lindent al... |
252 |
int action = UNINSTALL_NOTIFY_HANDLER; |
1da177e4c Linux-2.6.12-rc2 |
253 |
|
1da177e4c Linux-2.6.12-rc2 |
254 255 |
acpi_walk_namespace(ACPI_TYPE_DEVICE, |
4be44fcd3 [ACPI] Lindent al... |
256 257 |
ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, |
2263576cf ACPICA: Add post-... |
258 |
container_walk_namespace_cb, NULL, &action, NULL); |
1da177e4c Linux-2.6.12-rc2 |
259 260 |
acpi_bus_unregister_driver(&acpi_container_driver); |
d550d98d3 ACPI: delete trac... |
261 |
return; |
1da177e4c Linux-2.6.12-rc2 |
262 263 264 265 |
} module_init(acpi_container_init); module_exit(acpi_container_exit); |