Rev 1628 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1628 | Rev 1867 | ||
---|---|---|---|
1 | #include |
1 | #include |
2 | #include |
2 | #include |
3 | #include |
3 | #include |
4 | #include |
4 | #include |
5 | #include |
5 | #include |
6 | 6 | ||
7 | #include "acpi.h" |
7 | #include "acpi.h" |
8 | #include "acpi_bus.h" |
8 | #include "acpi_bus.h" |
9 | 9 | ||
10 | 10 | ||
11 | #define PREFIX "ACPI: " |
11 | #define PREFIX "ACPI: " |
12 | 12 | ||
13 | #define ACPI_BUS_CLASS "system_bus" |
13 | #define ACPI_BUS_CLASS "system_bus" |
14 | #define ACPI_BUS_HID "KLBSYBUS" |
14 | #define ACPI_BUS_HID "KLBSYBUS" |
15 | #define ACPI_BUS_DEVICE_NAME "System Bus" |
15 | #define ACPI_BUS_DEVICE_NAME "System Bus" |
16 | 16 | ||
17 | 17 | ||
18 | #define ACPI_IS_ROOT_DEVICE(device) (!(device)->parent) |
18 | #define ACPI_IS_ROOT_DEVICE(device) (!(device)->parent) |
19 | 19 | ||
20 | #define STRUCT_TO_INT(s) (*((int*)&s)) |
20 | #define STRUCT_TO_INT(s) (*((int*)&s)) |
21 | 21 | ||
22 | 22 | ||
23 | extern struct acpi_device *acpi_root; |
23 | extern struct acpi_device *acpi_root; |
24 | 24 | ||
25 | static LIST_HEAD(acpi_device_list); |
25 | extern struct list_head acpi_device_list; |
26 | static LIST_HEAD(acpi_bus_id_list); |
26 | extern struct list_head acpi_bus_id_list; |
27 | DEFINE_MUTEX(acpi_device_lock); |
27 | |
- | 28 | DEFINE_MUTEX(acpi_device_lock); |
|
28 | 29 | ||
29 | 30 | ||
30 | struct acpi_device_bus_id{ |
31 | struct acpi_device_bus_id{ |
31 | char bus_id[15]; |
32 | char bus_id[15]; |
32 | unsigned int instance_no; |
33 | unsigned int instance_no; |
33 | struct list_head node; |
34 | struct list_head node; |
34 | }; |
35 | }; |
35 | 36 | ||
36 | 37 | ||
37 | struct acpi_hardware_id { |
38 | struct acpi_hardware_id { |
38 | struct list_head list; |
39 | struct list_head list; |
39 | char *id; |
40 | char *id; |
40 | }; |
41 | }; |
41 | 42 | ||
42 | #define acpi_device_name(d) ((d)->pnp.device_name) |
43 | #define acpi_device_name(d) ((d)->pnp.device_name) |
43 | #define acpi_device_class(d) ((d)->pnp.device_class) |
44 | #define acpi_device_class(d) ((d)->pnp.device_class) |
44 | 45 | ||
45 | 46 | ||
46 | static void |
47 | static void |
47 | acpi_util_eval_error(ACPI_HANDLE h, ACPI_STRING p, ACPI_STATUS s) |
48 | acpi_util_eval_error(ACPI_HANDLE h, ACPI_STRING p, ACPI_STATUS s) |
48 | { |
49 | { |
49 | #ifdef ACPI_DEBUG_OUTPUT |
50 | #ifdef ACPI_DEBUG_OUTPUT |
50 | char prefix[80] = {'\0'}; |
51 | char prefix[80] = {'\0'}; |
51 | ACPI_BUFFER buffer = {sizeof(prefix), prefix}; |
52 | ACPI_BUFFER buffer = {sizeof(prefix), prefix}; |
52 | AcpiGetName(h, ACPI_FULL_PATHNAME, &buffer); |
53 | AcpiGetName(h, ACPI_FULL_PATHNAME, &buffer); |
53 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluate [%s.%s]: %s\n", |
54 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluate [%s.%s]: %s\n", |
54 | (char *) prefix, p, AcpiFormatException(s))); |
55 | (char *) prefix, p, AcpiFormatException(s))); |
55 | #else |
56 | #else |
56 | return; |
57 | return; |
57 | #endif |
58 | #endif |
58 | } |
59 | } |
59 | 60 | ||
60 | ACPI_STATUS |
61 | ACPI_STATUS |
61 | acpi_evaluate_integer(ACPI_HANDLE handle, ACPI_STRING pathname, |
62 | acpi_evaluate_integer(ACPI_HANDLE handle, ACPI_STRING pathname, |
62 | ACPI_OBJECT_LIST *arguments, unsigned long long *data) |
63 | ACPI_OBJECT_LIST *arguments, unsigned long long *data) |
63 | { |
64 | { |
64 | ACPI_STATUS status = AE_OK; |
65 | ACPI_STATUS status = AE_OK; |
65 | ACPI_OBJECT element; |
66 | ACPI_OBJECT element; |
66 | ACPI_BUFFER buffer = { 0, NULL }; |
67 | ACPI_BUFFER buffer = { 0, NULL }; |
67 | 68 | ||
68 | if (!data) |
69 | if (!data) |
69 | return AE_BAD_PARAMETER; |
70 | return AE_BAD_PARAMETER; |
70 | 71 | ||
71 | buffer.Length = sizeof(ACPI_OBJECT); |
72 | buffer.Length = sizeof(ACPI_OBJECT); |
72 | buffer.Pointer = &element; |
73 | buffer.Pointer = &element; |
73 | status = AcpiEvaluateObject(handle, pathname, arguments, &buffer); |
74 | status = AcpiEvaluateObject(handle, pathname, arguments, &buffer); |
74 | if (ACPI_FAILURE(status)) { |
75 | if (ACPI_FAILURE(status)) { |
75 | acpi_util_eval_error(handle, pathname, status); |
76 | acpi_util_eval_error(handle, pathname, status); |
76 | return status; |
77 | return status; |
77 | } |
78 | } |
78 | 79 | ||
79 | if (element.Type != ACPI_TYPE_INTEGER) { |
80 | if (element.Type != ACPI_TYPE_INTEGER) { |
80 | acpi_util_eval_error(handle, pathname, AE_BAD_DATA); |
81 | acpi_util_eval_error(handle, pathname, AE_BAD_DATA); |
81 | return AE_BAD_DATA; |
82 | return AE_BAD_DATA; |
82 | } |
83 | } |
83 | 84 | ||
84 | *data = element.Integer.Value; |
85 | *data = element.Integer.Value; |
85 | 86 | ||
86 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Return value [%llu]\n", *data)); |
87 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Return value [%llu]\n", *data)); |
87 | 88 | ||
88 | return AE_OK; |
89 | return AE_OK; |
89 | } |
90 | } |
90 | 91 | ||
91 | 92 | ||
92 | void acpi_bus_data_handler(ACPI_HANDLE handle, void *context) |
93 | void acpi_bus_data_handler(ACPI_HANDLE handle, void *context) |
93 | { |
94 | { |
94 | 95 | ||
95 | /* TBD */ |
96 | /* TBD */ |
96 | 97 | ||
97 | return; |
98 | return; |
98 | } |
99 | } |
99 | 100 | ||
100 | int acpi_bus_get_device(ACPI_HANDLE handle, struct acpi_device **device) |
101 | int acpi_bus_get_device(ACPI_HANDLE handle, struct acpi_device **device) |
101 | { |
102 | { |
102 | ACPI_STATUS status = AE_OK; |
103 | ACPI_STATUS status = AE_OK; |
103 | 104 | ||
104 | if (!device) |
105 | if (!device) |
105 | { |
106 | { |
106 | return -EINVAL; |
107 | return -EINVAL; |
107 | }; |
108 | }; |
108 | 109 | ||
109 | /* TBD: Support fixed-feature devices */ |
110 | /* TBD: Support fixed-feature devices */ |
110 | 111 | ||
111 | status = AcpiGetData(handle, acpi_bus_data_handler, (void **)device); |
112 | status = AcpiGetData(handle, acpi_bus_data_handler, (void **)device); |
112 | if (ACPI_FAILURE(status) || !*device) { |
113 | if (ACPI_FAILURE(status) || !*device) { |
113 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No context for object [%p]\n", |
114 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No context for object [%p]\n", |
114 | handle)); |
115 | handle)); |
115 | return -ENODEV; |
116 | return -ENODEV; |
116 | } |
117 | } |
117 | return 0; |
118 | return 0; |
118 | } |
119 | } |
119 | 120 | ||
120 | 121 | ||
121 | ACPI_STATUS acpi_bus_get_status_handle(ACPI_HANDLE handle, |
122 | ACPI_STATUS acpi_bus_get_status_handle(ACPI_HANDLE handle, |
122 | unsigned long long *sta) |
123 | unsigned long long *sta) |
123 | { |
124 | { |
124 | ACPI_STATUS status; |
125 | ACPI_STATUS status; |
125 | 126 | ||
126 | status = acpi_evaluate_integer(handle, "_STA", NULL, sta); |
127 | status = acpi_evaluate_integer(handle, "_STA", NULL, sta); |
127 | if (ACPI_SUCCESS(status)) |
128 | if (ACPI_SUCCESS(status)) |
128 | { |
129 | { |
129 | return AE_OK; |
130 | return AE_OK; |
130 | }; |
131 | }; |
131 | 132 | ||
132 | if (status == AE_NOT_FOUND) |
133 | if (status == AE_NOT_FOUND) |
133 | { |
134 | { |
134 | *sta = ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED | |
135 | *sta = ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED | |
135 | ACPI_STA_DEVICE_UI | ACPI_STA_DEVICE_FUNCTIONING; |
136 | ACPI_STA_DEVICE_UI | ACPI_STA_DEVICE_FUNCTIONING; |
136 | return AE_OK; |
137 | return AE_OK; |
137 | } |
138 | } |
138 | return status; |
139 | return status; |
139 | } |
140 | } |
140 | 141 | ||
141 | 142 | ||
142 | 143 | ||
143 | /* -------------------------------------------------------------------------- |
144 | /* -------------------------------------------------------------------------- |
144 | ACPI Bus operations |
145 | ACPI Bus operations |
145 | -------------------------------------------------------------------------- */ |
146 | -------------------------------------------------------------------------- */ |
146 | 147 | ||
147 | int acpi_match_device_ids(struct acpi_device *device, |
148 | int acpi_match_device_ids(struct acpi_device *device, |
148 | const struct acpi_device_ids *ids) |
149 | const struct acpi_device_ids *ids) |
149 | { |
150 | { |
150 | const struct acpi_device_ids *id; |
151 | const struct acpi_device_ids *id; |
151 | struct acpi_hardware_id *hwid; |
152 | struct acpi_hardware_id *hwid; |
152 | 153 | ||
153 | /* |
154 | /* |
154 | * If the device is not present, it is unnecessary to load device |
155 | * If the device is not present, it is unnecessary to load device |
155 | * driver for it. |
156 | * driver for it. |
156 | */ |
157 | */ |
157 | // if (!device->status.present) |
158 | // if (!device->status.present) |
158 | // return -ENODEV; |
159 | // return -ENODEV; |
159 | 160 | ||
160 | for (id = ids; id->id[0]; id++) |
161 | for (id = ids; id->id[0]; id++) |
161 | list_for_each_entry(hwid, &device->pnp.ids, list) |
162 | list_for_each_entry(hwid, &device->pnp.ids, list) |
162 | if (!strcmp((char *) id->id, hwid->id)) |
163 | if (!strcmp((char *) id->id, hwid->id)) |
163 | return 0; |
164 | return 0; |
164 | 165 | ||
165 | return -ENOENT; |
166 | return -ENOENT; |
166 | } |
167 | } |
167 | 168 | ||
168 | 169 | ||
169 | static int acpi_device_register(struct acpi_device *device) |
170 | static int acpi_device_register(struct acpi_device *device) |
170 | { |
171 | { |
171 | int result; |
172 | int result; |
172 | struct acpi_device_bus_id *acpi_device_bus_id, *new_bus_id; |
173 | struct acpi_device_bus_id *acpi_device_bus_id, *new_bus_id; |
173 | int found = 0; |
174 | int found = 0; |
174 | 175 | ||
175 | /* |
176 | /* |
176 | * Linkage |
177 | * Linkage |
177 | * ------- |
178 | * ------- |
178 | * Link this device to its parent and siblings. |
179 | * Link this device to its parent and siblings. |
179 | */ |
180 | */ |
180 | INIT_LIST_HEAD(&device->children); |
181 | INIT_LIST_HEAD(&device->children); |
181 | INIT_LIST_HEAD(&device->node); |
182 | INIT_LIST_HEAD(&device->node); |
182 | 183 | ||
183 | new_bus_id = kzalloc(sizeof(struct acpi_device_bus_id), GFP_KERNEL); |
184 | new_bus_id = kzalloc(sizeof(struct acpi_device_bus_id), GFP_KERNEL); |
184 | if (!new_bus_id) { |
185 | if (!new_bus_id) { |
185 | printk(KERN_ERR PREFIX "Memory allocation error\n"); |
186 | printk(KERN_ERR PREFIX "Memory allocation error\n"); |
186 | return -ENOMEM; |
187 | return -ENOMEM; |
187 | } |
188 | } |
188 | 189 | ||
189 | mutex_lock(&acpi_device_lock); |
190 | mutex_lock(&acpi_device_lock); |
190 | /* |
191 | /* |
191 | * Find suitable bus_id and instance number in acpi_bus_id_list |
192 | * Find suitable bus_id and instance number in acpi_bus_id_list |
192 | * If failed, create one and link it into acpi_bus_id_list |
193 | * If failed, create one and link it into acpi_bus_id_list |
193 | */ |
194 | */ |
194 | list_for_each_entry(acpi_device_bus_id, &acpi_bus_id_list, node) |
195 | list_for_each_entry(acpi_device_bus_id, &acpi_bus_id_list, node) |
195 | { |
196 | { |
196 | if (!strcmp(acpi_device_bus_id->bus_id, |
197 | if (!strcmp(acpi_device_bus_id->bus_id, |
197 | acpi_device_hid(device))) |
198 | acpi_device_hid(device))) |
198 | { |
199 | { |
199 | acpi_device_bus_id->instance_no++; |
200 | acpi_device_bus_id->instance_no++; |
200 | found = 1; |
201 | found = 1; |
201 | kfree(new_bus_id); |
202 | kfree(new_bus_id); |
202 | break; |
203 | break; |
203 | } |
204 | } |
204 | }; |
205 | }; |
205 | 206 | ||
206 | if (!found) |
207 | if (!found) |
207 | { |
208 | { |
208 | acpi_device_bus_id = new_bus_id; |
209 | acpi_device_bus_id = new_bus_id; |
209 | strcpy(acpi_device_bus_id->bus_id, acpi_device_hid(device)); |
210 | strcpy(acpi_device_bus_id->bus_id, acpi_device_hid(device)); |
210 | acpi_device_bus_id->instance_no = 0; |
211 | acpi_device_bus_id->instance_no = 0; |
211 | list_add_tail(&acpi_device_bus_id->node, &acpi_bus_id_list); |
212 | list_add_tail(&acpi_device_bus_id->node, &acpi_bus_id_list); |
212 | } |
213 | } |
213 | 214 | ||
214 | // dev_set_name(&device->dev, "%s:%02x", acpi_device_bus_id->bus_id, acpi_device_bus_id->instance_no); |
215 | // dev_set_name(&device->dev, "%s:%02x", acpi_device_bus_id->bus_id, acpi_device_bus_id->instance_no); |
215 | 216 | ||
216 | if (device->parent) |
217 | if (device->parent) |
217 | list_add_tail(&device->node, &device->parent->children); |
218 | list_add_tail(&device->node, &device->parent->children); |
218 | 219 | ||
219 | mutex_unlock(&acpi_device_lock); |
220 | mutex_unlock(&acpi_device_lock); |
220 | 221 | ||
221 | // device->dev.bus = &acpi_bus_type; |
222 | // device->dev.bus = &acpi_bus_type; |
222 | // device->dev.release = &acpi_device_release; |
223 | // device->dev.release = &acpi_device_release; |
223 | // result = device_register(&device->dev); |
224 | // result = device_register(&device->dev); |
224 | // if (result) { |
225 | // if (result) { |
225 | // dev_err(&device->dev, "Error registering device\n"); |
226 | // dev_err(&device->dev, "Error registering device\n"); |
226 | // goto end; |
227 | // goto end; |
227 | // } |
228 | // } |
228 | 229 | ||
229 | 230 | ||
230 | // device->removal_type = ACPI_BUS_REMOVAL_NORMAL; |
231 | // device->removal_type = ACPI_BUS_REMOVAL_NORMAL; |
231 | return 0; |
232 | return 0; |
232 | end: |
233 | end: |
233 | mutex_lock(&acpi_device_lock); |
234 | mutex_lock(&acpi_device_lock); |
234 | if (device->parent) |
235 | if (device->parent) |
235 | list_del(&device->node); |
236 | list_del(&device->node); |
236 | mutex_unlock(&acpi_device_lock); |
237 | mutex_unlock(&acpi_device_lock); |
237 | return result; |
238 | return result; |
238 | } |
239 | } |
239 | 240 | ||
240 | 241 | ||
241 | static struct acpi_device *acpi_bus_get_parent(ACPI_HANDLE handle) |
242 | static struct acpi_device *acpi_bus_get_parent(ACPI_HANDLE handle) |
242 | { |
243 | { |
243 | ACPI_STATUS status; |
244 | ACPI_STATUS status; |
244 | struct acpi_device *device; |
245 | struct acpi_device *device; |
245 | int ret; |
246 | int ret; |
246 | 247 | ||
247 | /* |
248 | /* |
248 | * Fixed hardware devices do not appear in the namespace and do not |
249 | * Fixed hardware devices do not appear in the namespace and do not |
249 | * have handles, but we fabricate acpi_devices for them, so we have |
250 | * have handles, but we fabricate acpi_devices for them, so we have |
250 | * to deal with them specially. |
251 | * to deal with them specially. |
251 | */ |
252 | */ |
252 | if (handle == NULL) |
253 | if (handle == NULL) |
253 | return acpi_root; |
254 | return acpi_root; |
254 | 255 | ||
255 | do { |
256 | do { |
256 | status = AcpiGetParent(handle, &handle); |
257 | status = AcpiGetParent(handle, &handle); |
257 | if (status == AE_NULL_ENTRY) |
258 | if (status == AE_NULL_ENTRY) |
258 | return NULL; |
259 | return NULL; |
259 | if (ACPI_FAILURE(status)) |
260 | if (ACPI_FAILURE(status)) |
260 | return acpi_root; |
261 | return acpi_root; |
261 | 262 | ||
262 | ret = acpi_bus_get_device(handle, &device); |
263 | ret = acpi_bus_get_device(handle, &device); |
263 | if (ret == 0) |
264 | if (ret == 0) |
264 | return device; |
265 | return device; |
265 | } while (1); |
266 | } while (1); |
266 | } |
267 | } |
267 | 268 | ||
268 | 269 | ||
269 | static int acpi_bus_get_flags(struct acpi_device *device) |
270 | static int acpi_bus_get_flags(struct acpi_device *device) |
270 | { |
271 | { |
271 | ACPI_STATUS status = AE_OK; |
272 | ACPI_STATUS status = AE_OK; |
272 | ACPI_HANDLE temp = NULL; |
273 | ACPI_HANDLE temp = NULL; |
273 | 274 | ||
274 | /* Presence of _STA indicates 'dynamic_status' */ |
275 | /* Presence of _STA indicates 'dynamic_status' */ |
275 | status = AcpiGetHandle(device->handle, "_STA", &temp); |
276 | status = AcpiGetHandle(device->handle, "_STA", &temp); |
276 | if (ACPI_SUCCESS(status)) |
277 | if (ACPI_SUCCESS(status)) |
277 | device->flags.dynamic_status = 1; |
278 | device->flags.dynamic_status = 1; |
278 | 279 | ||
279 | /* Presence of _RMV indicates 'removable' */ |
280 | /* Presence of _RMV indicates 'removable' */ |
280 | status = AcpiGetHandle(device->handle, "_RMV", &temp); |
281 | status = AcpiGetHandle(device->handle, "_RMV", &temp); |
281 | if (ACPI_SUCCESS(status)) |
282 | if (ACPI_SUCCESS(status)) |
282 | device->flags.removable = 1; |
283 | device->flags.removable = 1; |
283 | 284 | ||
284 | /* Presence of _EJD|_EJ0 indicates 'ejectable' */ |
285 | /* Presence of _EJD|_EJ0 indicates 'ejectable' */ |
285 | status = AcpiGetHandle(device->handle, "_EJD", &temp); |
286 | status = AcpiGetHandle(device->handle, "_EJD", &temp); |
286 | if (ACPI_SUCCESS(status)) |
287 | if (ACPI_SUCCESS(status)) |
287 | device->flags.ejectable = 1; |
288 | device->flags.ejectable = 1; |
288 | else { |
289 | else { |
289 | status = AcpiGetHandle(device->handle, "_EJ0", &temp); |
290 | status = AcpiGetHandle(device->handle, "_EJ0", &temp); |
290 | if (ACPI_SUCCESS(status)) |
291 | if (ACPI_SUCCESS(status)) |
291 | device->flags.ejectable = 1; |
292 | device->flags.ejectable = 1; |
292 | } |
293 | } |
293 | 294 | ||
294 | /* Presence of _LCK indicates 'lockable' */ |
295 | /* Presence of _LCK indicates 'lockable' */ |
295 | status = AcpiGetHandle(device->handle, "_LCK", &temp); |
296 | status = AcpiGetHandle(device->handle, "_LCK", &temp); |
296 | if (ACPI_SUCCESS(status)) |
297 | if (ACPI_SUCCESS(status)) |
297 | device->flags.lockable = 1; |
298 | device->flags.lockable = 1; |
298 | 299 | ||
299 | /* Presence of _PS0|_PR0 indicates 'power manageable' */ |
300 | /* Presence of _PS0|_PR0 indicates 'power manageable' */ |
300 | status = AcpiGetHandle(device->handle, "_PS0", &temp); |
301 | status = AcpiGetHandle(device->handle, "_PS0", &temp); |
301 | if (ACPI_FAILURE(status)) |
302 | if (ACPI_FAILURE(status)) |
302 | status = AcpiGetHandle(device->handle, "_PR0", &temp); |
303 | status = AcpiGetHandle(device->handle, "_PR0", &temp); |
303 | if (ACPI_SUCCESS(status)) |
304 | if (ACPI_SUCCESS(status)) |
304 | device->flags.power_manageable = 1; |
305 | device->flags.power_manageable = 1; |
305 | 306 | ||
306 | /* Presence of _PRW indicates wake capable */ |
307 | /* Presence of _PRW indicates wake capable */ |
307 | status = AcpiGetHandle(device->handle, "_PRW", &temp); |
308 | status = AcpiGetHandle(device->handle, "_PRW", &temp); |
308 | if (ACPI_SUCCESS(status)) |
309 | if (ACPI_SUCCESS(status)) |
309 | device->flags.wake_capable = 1; |
310 | device->flags.wake_capable = 1; |
310 | 311 | ||
311 | /* TBD: Performance management */ |
312 | /* TBD: Performance management */ |
312 | 313 | ||
313 | return 0; |
314 | return 0; |
314 | } |
315 | } |
315 | 316 | ||
316 | static void acpi_device_get_busid(struct acpi_device *device) |
317 | static void acpi_device_get_busid(struct acpi_device *device) |
317 | { |
318 | { |
318 | char bus_id[5] = { '?', 0 }; |
319 | char bus_id[5] = { '?', 0 }; |
319 | struct acpi_buffer buffer = { sizeof(bus_id), bus_id }; |
320 | struct acpi_buffer buffer = { sizeof(bus_id), bus_id }; |
320 | int i = 0; |
321 | int i = 0; |
321 | 322 | ||
322 | /* |
323 | /* |
323 | * Bus ID |
324 | * Bus ID |
324 | * ------ |
325 | * ------ |
325 | * The device's Bus ID is simply the object name. |
326 | * The device's Bus ID is simply the object name. |
326 | * TBD: Shouldn't this value be unique (within the ACPI namespace)? |
327 | * TBD: Shouldn't this value be unique (within the ACPI namespace)? |
327 | */ |
328 | */ |
328 | if (ACPI_IS_ROOT_DEVICE(device)) { |
329 | if (ACPI_IS_ROOT_DEVICE(device)) { |
329 | strcpy(device->pnp.bus_id, "ACPI"); |
330 | strcpy(device->pnp.bus_id, "ACPI"); |
330 | return; |
331 | return; |
331 | } |
332 | } |
332 | 333 | ||
333 | switch (device->device_type) |
334 | switch (device->device_type) |
334 | { |
335 | { |
335 | case ACPI_BUS_TYPE_POWER_BUTTON: |
336 | case ACPI_BUS_TYPE_POWER_BUTTON: |
336 | strcpy(device->pnp.bus_id, "PWRF"); |
337 | strcpy(device->pnp.bus_id, "PWRF"); |
337 | break; |
338 | break; |
338 | case ACPI_BUS_TYPE_SLEEP_BUTTON: |
339 | case ACPI_BUS_TYPE_SLEEP_BUTTON: |
339 | strcpy(device->pnp.bus_id, "SLPF"); |
340 | strcpy(device->pnp.bus_id, "SLPF"); |
340 | break; |
341 | break; |
341 | default: |
342 | default: |
342 | AcpiGetName(device->handle, ACPI_SINGLE_NAME, &buffer); |
343 | AcpiGetName(device->handle, ACPI_SINGLE_NAME, &buffer); |
343 | /* Clean up trailing underscores (if any) */ |
344 | /* Clean up trailing underscores (if any) */ |
344 | for (i = 3; i > 1; i--) { |
345 | for (i = 3; i > 1; i--) { |
345 | if (bus_id[i] == '_') |
346 | if (bus_id[i] == '_') |
346 | bus_id[i] = '\0'; |
347 | bus_id[i] = '\0'; |
347 | else |
348 | else |
348 | break; |
349 | break; |
349 | } |
350 | } |
350 | strcpy(device->pnp.bus_id, bus_id); |
351 | strcpy(device->pnp.bus_id, bus_id); |
351 | break; |
352 | break; |
352 | } |
353 | } |
353 | } |
354 | } |
354 | 355 | ||
355 | 356 | ||
356 | #define ACPI_VIDEO_OUTPUT_SWITCHING 0x0001 |
357 | #define ACPI_VIDEO_OUTPUT_SWITCHING 0x0001 |
357 | #define ACPI_VIDEO_DEVICE_POSTING 0x0002 |
358 | #define ACPI_VIDEO_DEVICE_POSTING 0x0002 |
358 | #define ACPI_VIDEO_ROM_AVAILABLE 0x0004 |
359 | #define ACPI_VIDEO_ROM_AVAILABLE 0x0004 |
359 | #define ACPI_VIDEO_BACKLIGHT 0x0008 |
360 | #define ACPI_VIDEO_BACKLIGHT 0x0008 |
360 | #define ACPI_VIDEO_BACKLIGHT_FORCE_VENDOR 0x0010 |
361 | #define ACPI_VIDEO_BACKLIGHT_FORCE_VENDOR 0x0010 |
361 | #define ACPI_VIDEO_BACKLIGHT_FORCE_VIDEO 0x0020 |
362 | #define ACPI_VIDEO_BACKLIGHT_FORCE_VIDEO 0x0020 |
362 | #define ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VENDOR 0x0040 |
363 | #define ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VENDOR 0x0040 |
363 | #define ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VIDEO 0x0080 |
364 | #define ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VIDEO 0x0080 |
364 | #define ACPI_VIDEO_BACKLIGHT_DMI_VENDOR 0x0100 |
365 | #define ACPI_VIDEO_BACKLIGHT_DMI_VENDOR 0x0100 |
365 | #define ACPI_VIDEO_BACKLIGHT_DMI_VIDEO 0x0200 |
366 | #define ACPI_VIDEO_BACKLIGHT_DMI_VIDEO 0x0200 |
366 | #define ACPI_VIDEO_OUTPUT_SWITCHING_DMI_VENDOR 0x0400 |
367 | #define ACPI_VIDEO_OUTPUT_SWITCHING_DMI_VENDOR 0x0400 |
367 | #define ACPI_VIDEO_OUTPUT_SWITCHING_DMI_VIDEO 0x0800 |
368 | #define ACPI_VIDEO_OUTPUT_SWITCHING_DMI_VIDEO 0x0800 |
368 | 369 | ||
369 | 370 | ||
370 | long acpi_is_video_device(struct acpi_device *device) |
371 | long acpi_is_video_device(struct acpi_device *device) |
371 | { |
372 | { |
372 | ACPI_HANDLE h_dummy; |
373 | ACPI_HANDLE h_dummy; |
373 | long video_caps = 0; |
374 | long video_caps = 0; |
374 | 375 | ||
375 | if (!device) |
376 | if (!device) |
376 | return 0; |
377 | return 0; |
377 | 378 | ||
378 | /* Is this device able to support video switching ? */ |
379 | /* Is this device able to support video switching ? */ |
379 | if (ACPI_SUCCESS(AcpiGetHandle(device->handle, "_DOD", &h_dummy)) || |
380 | if (ACPI_SUCCESS(AcpiGetHandle(device->handle, "_DOD", &h_dummy)) || |
380 | ACPI_SUCCESS(AcpiGetHandle(device->handle, "_DOS", &h_dummy))) |
381 | ACPI_SUCCESS(AcpiGetHandle(device->handle, "_DOS", &h_dummy))) |
381 | video_caps |= ACPI_VIDEO_OUTPUT_SWITCHING; |
382 | video_caps |= ACPI_VIDEO_OUTPUT_SWITCHING; |
382 | 383 | ||
383 | /* Is this device able to retrieve a video ROM ? */ |
384 | /* Is this device able to retrieve a video ROM ? */ |
384 | if (ACPI_SUCCESS(AcpiGetHandle(device->handle, "_ROM", &h_dummy))) |
385 | if (ACPI_SUCCESS(AcpiGetHandle(device->handle, "_ROM", &h_dummy))) |
385 | video_caps |= ACPI_VIDEO_ROM_AVAILABLE; |
386 | video_caps |= ACPI_VIDEO_ROM_AVAILABLE; |
386 | 387 | ||
387 | /* Is this device able to configure which video head to be POSTed ? */ |
388 | /* Is this device able to configure which video head to be POSTed ? */ |
388 | if (ACPI_SUCCESS(AcpiGetHandle(device->handle, "_VPO", &h_dummy)) && |
389 | if (ACPI_SUCCESS(AcpiGetHandle(device->handle, "_VPO", &h_dummy)) && |
389 | ACPI_SUCCESS(AcpiGetHandle(device->handle, "_GPD", &h_dummy)) && |
390 | ACPI_SUCCESS(AcpiGetHandle(device->handle, "_GPD", &h_dummy)) && |
390 | ACPI_SUCCESS(AcpiGetHandle(device->handle, "_SPD", &h_dummy))) |
391 | ACPI_SUCCESS(AcpiGetHandle(device->handle, "_SPD", &h_dummy))) |
391 | video_caps |= ACPI_VIDEO_DEVICE_POSTING; |
392 | video_caps |= ACPI_VIDEO_DEVICE_POSTING; |
392 | 393 | ||
393 | return video_caps; |
394 | return video_caps; |
394 | } |
395 | } |
395 | 396 | ||
396 | /* |
397 | /* |
397 | * acpi_bay_match - see if a device is an ejectable driver bay |
398 | * acpi_bay_match - see if a device is an ejectable driver bay |
398 | * |
399 | * |
399 | * If an acpi object is ejectable and has one of the ACPI ATA methods defined, |
400 | * If an acpi object is ejectable and has one of the ACPI ATA methods defined, |
400 | * then we can safely call it an ejectable drive bay |
401 | * then we can safely call it an ejectable drive bay |
401 | */ |
402 | */ |
402 | static int acpi_bay_match(struct acpi_device *device){ |
403 | static int acpi_bay_match(struct acpi_device *device){ |
403 | ACPI_STATUS status; |
404 | ACPI_STATUS status; |
404 | ACPI_HANDLE handle; |
405 | ACPI_HANDLE handle; |
405 | ACPI_HANDLE tmp; |
406 | ACPI_HANDLE tmp; |
406 | ACPI_HANDLE phandle; |
407 | ACPI_HANDLE phandle; |
407 | 408 | ||
408 | handle = device->handle; |
409 | handle = device->handle; |
409 | 410 | ||
410 | status = AcpiGetHandle(handle, "_EJ0", &tmp); |
411 | status = AcpiGetHandle(handle, "_EJ0", &tmp); |
411 | if (ACPI_FAILURE(status)) |
412 | if (ACPI_FAILURE(status)) |
412 | return -ENODEV; |
413 | return -ENODEV; |
413 | 414 | ||
414 | if ((ACPI_SUCCESS(AcpiGetHandle(handle, "_GTF", &tmp))) || |
415 | if ((ACPI_SUCCESS(AcpiGetHandle(handle, "_GTF", &tmp))) || |
415 | (ACPI_SUCCESS(AcpiGetHandle(handle, "_GTM", &tmp))) || |
416 | (ACPI_SUCCESS(AcpiGetHandle(handle, "_GTM", &tmp))) || |
416 | (ACPI_SUCCESS(AcpiGetHandle(handle, "_STM", &tmp))) || |
417 | (ACPI_SUCCESS(AcpiGetHandle(handle, "_STM", &tmp))) || |
417 | (ACPI_SUCCESS(AcpiGetHandle(handle, "_SDD", &tmp)))) |
418 | (ACPI_SUCCESS(AcpiGetHandle(handle, "_SDD", &tmp)))) |
418 | return 0; |
419 | return 0; |
419 | 420 | ||
420 | if (AcpiGetParent(handle, &phandle)) |
421 | if (AcpiGetParent(handle, &phandle)) |
421 | return -ENODEV; |
422 | return -ENODEV; |
422 | 423 | ||
423 | if ((ACPI_SUCCESS(AcpiGetHandle(phandle, "_GTF", &tmp))) || |
424 | if ((ACPI_SUCCESS(AcpiGetHandle(phandle, "_GTF", &tmp))) || |
424 | (ACPI_SUCCESS(AcpiGetHandle(phandle, "_GTM", &tmp))) || |
425 | (ACPI_SUCCESS(AcpiGetHandle(phandle, "_GTM", &tmp))) || |
425 | (ACPI_SUCCESS(AcpiGetHandle(phandle, "_STM", &tmp))) || |
426 | (ACPI_SUCCESS(AcpiGetHandle(phandle, "_STM", &tmp))) || |
426 | (ACPI_SUCCESS(AcpiGetHandle(phandle, "_SDD", &tmp)))) |
427 | (ACPI_SUCCESS(AcpiGetHandle(phandle, "_SDD", &tmp)))) |
427 | return 0; |
428 | return 0; |
428 | 429 | ||
429 | return -ENODEV; |
430 | return -ENODEV; |
430 | } |
431 | } |
431 | 432 | ||
432 | /* |
433 | /* |
433 | * acpi_dock_match - see if a device has a _DCK method |
434 | * acpi_dock_match - see if a device has a _DCK method |
434 | */ |
435 | */ |
435 | static int acpi_dock_match(struct acpi_device *device) |
436 | static int acpi_dock_match(struct acpi_device *device) |
436 | { |
437 | { |
437 | ACPI_HANDLE tmp; |
438 | ACPI_HANDLE tmp; |
438 | return AcpiGetHandle(device->handle, "_DCK", &tmp); |
439 | return AcpiGetHandle(device->handle, "_DCK", &tmp); |
439 | } |
440 | } |
440 | 441 | ||
441 | char *acpi_device_hid(struct acpi_device *device) |
442 | char *acpi_device_hid(struct acpi_device *device) |
442 | { |
443 | { |
443 | struct acpi_hardware_id *hid; |
444 | struct acpi_hardware_id *hid; |
444 | 445 | ||
445 | hid = list_first_entry(&device->pnp.ids, struct acpi_hardware_id, list); |
446 | hid = list_first_entry(&device->pnp.ids, struct acpi_hardware_id, list); |
446 | return hid->id; |
447 | return hid->id; |
447 | } |
448 | } |
448 | 449 | ||
449 | static void acpi_add_id(struct acpi_device *device, const char *dev_id) |
450 | static void acpi_add_id(struct acpi_device *device, const char *dev_id) |
450 | { |
451 | { |
451 | struct acpi_hardware_id *id; |
452 | struct acpi_hardware_id *id; |
452 | 453 | ||
453 | id = kmalloc(sizeof(*id), GFP_KERNEL); |
454 | id = kmalloc(sizeof(*id), GFP_KERNEL); |
454 | if (!id) |
455 | if (!id) |
455 | return; |
456 | return; |
456 | 457 | ||
457 | INIT_LIST_HEAD(&id->list); |
458 | INIT_LIST_HEAD(&id->list); |
458 | 459 | ||
459 | id->id = kmalloc(strlen(dev_id) + 1, GFP_KERNEL); |
460 | id->id = kmalloc(strlen(dev_id) + 1, GFP_KERNEL); |
460 | if (!id->id) { |
461 | if (!id->id) { |
461 | kfree(id); |
462 | kfree(id); |
462 | return; |
463 | return; |
463 | } |
464 | } |
464 | 465 | ||
465 | strcpy(id->id, dev_id); |
466 | strcpy(id->id, dev_id); |
466 | list_add_tail(&id->list, &device->pnp.ids); |
467 | list_add_tail(&id->list, &device->pnp.ids); |
467 | } |
468 | } |
468 | 469 | ||
469 | 470 | ||
470 | 471 | ||
471 | static void acpi_device_set_id(struct acpi_device *device) |
472 | static void acpi_device_set_id(struct acpi_device *device) |
472 | { |
473 | { |
473 | ACPI_STATUS status; |
474 | ACPI_STATUS status; |
474 | ACPI_DEVICE_INFO *info; |
475 | ACPI_DEVICE_INFO *info; |
475 | ACPI_DEVICE_ID_LIST *cid_list; |
476 | ACPI_DEVICE_ID_LIST *cid_list; |
476 | int i; |
477 | int i; |
477 | 478 | ||
478 | switch (device->device_type) |
479 | switch (device->device_type) |
479 | { |
480 | { |
480 | case ACPI_BUS_TYPE_DEVICE: |
481 | case ACPI_BUS_TYPE_DEVICE: |
481 | if (ACPI_IS_ROOT_DEVICE(device)) { |
482 | if (ACPI_IS_ROOT_DEVICE(device)) { |
482 | acpi_add_id(device, ACPI_SYSTEM_HID); |
483 | acpi_add_id(device, ACPI_SYSTEM_HID); |
483 | break; |
484 | break; |
484 | } |
485 | } |
485 | 486 | ||
486 | status = AcpiGetObjectInfo(device->handle, &info); |
487 | status = AcpiGetObjectInfo(device->handle, &info); |
487 | if (ACPI_FAILURE(status)) { |
488 | if (ACPI_FAILURE(status)) { |
488 | printk(KERN_ERR PREFIX "%s: Error reading device info\n", __func__); |
489 | printk(KERN_ERR PREFIX "%s: Error reading device info\n", __func__); |
489 | return; |
490 | return; |
490 | } |
491 | } |
491 | 492 | ||
492 | if (info->Valid & ACPI_VALID_HID) |
493 | if (info->Valid & ACPI_VALID_HID) |
493 | acpi_add_id(device, info->HardwareId.String); |
494 | acpi_add_id(device, info->HardwareId.String); |
494 | if (info->Valid & ACPI_VALID_CID) |
495 | if (info->Valid & ACPI_VALID_CID) |
495 | { |
496 | { |
496 | cid_list = &info->CompatibleIdList; |
497 | cid_list = &info->CompatibleIdList; |
497 | for (i = 0; i < cid_list->Count; i++) |
498 | for (i = 0; i < cid_list->Count; i++) |
498 | acpi_add_id(device, cid_list->Ids[i].String); |
499 | acpi_add_id(device, cid_list->Ids[i].String); |
499 | } |
500 | } |
500 | if (info->Valid & ACPI_VALID_ADR) { |
501 | if (info->Valid & ACPI_VALID_ADR) { |
501 | device->pnp.bus_address = info->Address; |
502 | device->pnp.bus_address = info->Address; |
502 | device->flags.bus_address = 1; |
503 | device->flags.bus_address = 1; |
503 | } |
504 | } |
504 | 505 | ||
505 | kfree(info); |
506 | kfree(info); |
506 | 507 | ||
507 | /* |
508 | /* |
508 | * Some devices don't reliably have _HIDs & _CIDs, so add |
509 | * Some devices don't reliably have _HIDs & _CIDs, so add |
509 | * synthetic HIDs to make sure drivers can find them. |
510 | * synthetic HIDs to make sure drivers can find them. |
510 | */ |
511 | */ |
511 | if (acpi_is_video_device(device)) |
512 | if (acpi_is_video_device(device)) |
512 | acpi_add_id(device, ACPI_VIDEO_HID); |
513 | acpi_add_id(device, ACPI_VIDEO_HID); |
513 | else if (ACPI_SUCCESS(acpi_bay_match(device))) |
514 | else if (ACPI_SUCCESS(acpi_bay_match(device))) |
514 | acpi_add_id(device, ACPI_BAY_HID); |
515 | acpi_add_id(device, ACPI_BAY_HID); |
515 | else if (ACPI_SUCCESS(acpi_dock_match(device))) |
516 | else if (ACPI_SUCCESS(acpi_dock_match(device))) |
516 | acpi_add_id(device, ACPI_DOCK_HID); |
517 | acpi_add_id(device, ACPI_DOCK_HID); |
517 | else if (!acpi_device_hid(device) && |
518 | else if (!acpi_device_hid(device) && |
518 | ACPI_IS_ROOT_DEVICE(device->parent)) { |
519 | ACPI_IS_ROOT_DEVICE(device->parent)) { |
519 | acpi_add_id(device, ACPI_BUS_HID); /* \_SB, LNXSYBUS */ |
520 | acpi_add_id(device, ACPI_BUS_HID); /* \_SB, LNXSYBUS */ |
520 | strcpy(device->pnp.device_name, ACPI_BUS_DEVICE_NAME); |
521 | strcpy(device->pnp.device_name, ACPI_BUS_DEVICE_NAME); |
521 | strcpy(device->pnp.device_class, ACPI_BUS_CLASS); |
522 | strcpy(device->pnp.device_class, ACPI_BUS_CLASS); |
522 | } |
523 | } |
523 | 524 | ||
524 | break; |
525 | break; |
525 | case ACPI_BUS_TYPE_POWER: |
526 | case ACPI_BUS_TYPE_POWER: |
526 | acpi_add_id(device, ACPI_POWER_HID); |
527 | acpi_add_id(device, ACPI_POWER_HID); |
527 | break; |
528 | break; |
528 | case ACPI_BUS_TYPE_PROCESSOR: |
529 | case ACPI_BUS_TYPE_PROCESSOR: |
529 | acpi_add_id(device, ACPI_PROCESSOR_OBJECT_HID); |
530 | acpi_add_id(device, ACPI_PROCESSOR_OBJECT_HID); |
530 | break; |
531 | break; |
531 | case ACPI_BUS_TYPE_THERMAL: |
532 | case ACPI_BUS_TYPE_THERMAL: |
532 | acpi_add_id(device, ACPI_THERMAL_HID); |
533 | acpi_add_id(device, ACPI_THERMAL_HID); |
533 | break; |
534 | break; |
534 | case ACPI_BUS_TYPE_POWER_BUTTON: |
535 | case ACPI_BUS_TYPE_POWER_BUTTON: |
535 | acpi_add_id(device, ACPI_BUTTON_HID_POWERF); |
536 | acpi_add_id(device, ACPI_BUTTON_HID_POWERF); |
536 | break; |
537 | break; |
537 | case ACPI_BUS_TYPE_SLEEP_BUTTON: |
538 | case ACPI_BUS_TYPE_SLEEP_BUTTON: |
538 | acpi_add_id(device, ACPI_BUTTON_HID_SLEEPF); |
539 | acpi_add_id(device, ACPI_BUTTON_HID_SLEEPF); |
539 | break; |
540 | break; |
540 | } |
541 | } |
541 | 542 | ||
542 | /* |
543 | /* |
543 | * We build acpi_devices for some objects that don't have _HID or _CID, |
544 | * We build acpi_devices for some objects that don't have _HID or _CID, |
544 | * e.g., PCI bridges and slots. Drivers can't bind to these objects, |
545 | * e.g., PCI bridges and slots. Drivers can't bind to these objects, |
545 | * but we do use them indirectly by traversing the acpi_device tree. |
546 | * but we do use them indirectly by traversing the acpi_device tree. |
546 | * This generic ID isn't useful for driver binding, but it provides |
547 | * This generic ID isn't useful for driver binding, but it provides |
547 | * the useful property that "every acpi_device has an ID." |
548 | * the useful property that "every acpi_device has an ID." |
548 | */ |
549 | */ |
549 | if (list_empty(&device->pnp.ids)) |
550 | if (list_empty(&device->pnp.ids)) |
550 | acpi_add_id(device, "device"); |
551 | acpi_add_id(device, "device"); |
551 | } |
552 | } |
552 | 553 | ||
553 | static int acpi_device_set_context(struct acpi_device *device) |
554 | static int acpi_device_set_context(struct acpi_device *device) |
554 | { |
555 | { |
555 | ACPI_STATUS status; |
556 | ACPI_STATUS status; |
556 | 557 | ||
557 | /* |
558 | /* |
558 | * Context |
559 | * Context |
559 | * ------- |
560 | * ------- |
560 | * Attach this 'struct acpi_device' to the ACPI object. This makes |
561 | * Attach this 'struct acpi_device' to the ACPI object. This makes |
561 | * resolutions from handle->device very efficient. Fixed hardware |
562 | * resolutions from handle->device very efficient. Fixed hardware |
562 | * devices have no handles, so we skip them. |
563 | * devices have no handles, so we skip them. |
563 | */ |
564 | */ |
564 | if (!device->handle) |
565 | if (!device->handle) |
565 | return 0; |
566 | return 0; |
566 | 567 | ||
567 | status = AcpiAttachData(device->handle, |
568 | status = AcpiAttachData(device->handle, |
568 | acpi_bus_data_handler, device); |
569 | acpi_bus_data_handler, device); |
569 | if (ACPI_SUCCESS(status)) |
570 | if (ACPI_SUCCESS(status)) |
570 | return 0; |
571 | return 0; |
571 | 572 | ||
572 | printk(KERN_ERR PREFIX "Error attaching device data\n"); |
573 | printk(KERN_ERR PREFIX "Error attaching device data\n"); |
573 | return -ENODEV; |
574 | return -ENODEV; |
574 | } |
575 | } |
575 | 576 | ||
576 | 577 | ||
577 | static int acpi_add_single_object(struct acpi_device **child, |
578 | static int acpi_add_single_object(struct acpi_device **child, |
578 | ACPI_HANDLE handle, int type, |
579 | ACPI_HANDLE handle, int type, |
579 | unsigned long long sta, |
580 | unsigned long long sta, |
580 | struct acpi_bus_ops *ops) |
581 | struct acpi_bus_ops *ops) |
581 | { |
582 | { |
582 | int result; |
583 | int result; |
583 | struct acpi_device *device; |
584 | struct acpi_device *device; |
584 | ACPI_BUFFER buffer = { ACPI_ALLOCATE_BUFFER, NULL }; |
585 | ACPI_BUFFER buffer = { ACPI_ALLOCATE_BUFFER, NULL }; |
585 | 586 | ACPI_DEVICE_INFO *info = NULL; |
|
586 | device = kzalloc(sizeof(struct acpi_device), GFP_KERNEL); |
587 | ACPI_DEVICE_ID_LIST *cid_list; |
- | 588 | int i; |
|
- | 589 | ||
- | 590 | ||
- | 591 | device = kzalloc(sizeof(struct acpi_device), GFP_KERNEL); |
|
587 | if (!device) { |
592 | if (!device) { |
588 | printk(KERN_ERR PREFIX "Memory allocation error\n"); |
593 | printk(KERN_ERR PREFIX "Memory allocation error\n"); |
589 | return -ENOMEM; |
594 | return -ENOMEM; |
590 | } |
595 | } |
591 | 596 | ||
592 | INIT_LIST_HEAD(&device->pnp.ids); |
597 | INIT_LIST_HEAD(&device->pnp.ids); |
593 | device->device_type = type; |
598 | device->device_type = type; |
594 | device->handle = handle; |
599 | device->handle = handle; |
595 | device->parent = acpi_bus_get_parent(handle); |
600 | device->parent = acpi_bus_get_parent(handle); |
596 | device->bus_ops = *ops; /* workround for not call .start */ |
601 | device->bus_ops = *ops; /* workround for not call .start */ |
597 | STRUCT_TO_INT(device->status) = sta; |
602 | STRUCT_TO_INT(device->status) = sta; |
598 | 603 | ||
599 | acpi_device_get_busid(device); |
604 | acpi_device_get_busid(device); |
600 | 605 | ||
601 | /* |
606 | /* |
602 | * Flags |
607 | * Flags |
603 | * ----- |
608 | * ----- |
604 | * Note that we only look for object handles -- cannot evaluate objects |
609 | * Note that we only look for object handles -- cannot evaluate objects |
605 | * until we know the device is present and properly initialized. |
610 | * until we know the device is present and properly initialized. |
606 | */ |
611 | */ |
607 | result = acpi_bus_get_flags(device); |
612 | result = acpi_bus_get_flags(device); |
608 | if (result) |
613 | if (result) |
609 | goto end; |
614 | goto end; |
610 | 615 | ||
611 | /* |
616 | /* |
612 | * Initialize Device |
617 | * Initialize Device |
613 | * ----------------- |
618 | * ----------------- |
614 | * TBD: Synch with Core's enumeration/initialization process. |
619 | * TBD: Synch with Core's enumeration/initialization process. |
615 | */ |
620 | */ |
616 | acpi_device_set_id(device); |
621 | acpi_device_set_id(device); |
617 | 622 | ||
618 | 623 | ||
619 | if ((result = acpi_device_set_context(device))) |
624 | if ((result = acpi_device_set_context(device))) |
620 | goto end; |
625 | goto end; |
621 | 626 | ||
622 | result = acpi_device_register(device); |
627 | result = acpi_device_register(device); |
623 | 628 | ||
624 | /* |
629 | /* |
625 | * Bind _ADR-Based Devices when hot add |
630 | * Bind _ADR-Based Devices when hot add |
626 | */ |
631 | */ |
627 | if (device->flags.bus_address) { |
632 | if (device->flags.bus_address) { |
628 | if (device->parent && device->parent->ops.bind) |
633 | if (device->parent && device->parent->ops.bind) |
629 | device->parent->ops.bind(device); |
634 | device->parent->ops.bind(device); |
630 | } |
635 | } |
631 | 636 | ||
632 | end: |
637 | end: |
633 | if (!result) { |
638 | |
634 | AcpiGetName(handle, ACPI_FULL_PATHNAME, &buffer); |
639 | AcpiGetName(handle, ACPI_FULL_PATHNAME, &buffer); |
635 | dbgprintf(PREFIX "Adding [%s]\n", (char *)buffer.Pointer); |
- | |
- | 640 | dbgprintf(PREFIX "Adding [%s]", (char *)buffer.Pointer); |
|
636 | kfree(buffer.Pointer); |
641 | kfree(buffer.Pointer); |
637 | *child = device; |
642 | |
638 | }; |
643 | AcpiGetObjectInfo(handle, &info); |
- | 644 | if (info->Valid & ACPI_VALID_HID) |
|
- | 645 | dbgprintf (" HID: %s", info->HardwareId.String); |
|
- | 646 | ||
- | 647 | if (info->Valid & ACPI_VALID_CID) |
|
- | 648 | { |
|
- | 649 | cid_list = &info->CompatibleIdList; |
|
- | 650 | for (i = 0; i < cid_list->Count; i++) |
|
- | 651 | dbgprintf(" CID: %s\n", cid_list->Ids[i].String); |
|
- | 652 | } |
|
- | 653 | dbgprintf("\n"); |
|
- | 654 | ||
- | 655 | kfree(info); |
|
- | 656 | ||
- | 657 | if (!result) { |
|
- | 658 | *child = device; |
|
- | 659 | }; |
|
639 | return result; |
660 | return result; |
640 | } |
661 | } |
641 | 662 | ||
642 | #define ACPI_STA_DEFAULT (ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED | \ |
663 | #define ACPI_STA_DEFAULT (ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED | \ |
643 | ACPI_STA_DEVICE_UI | ACPI_STA_DEVICE_FUNCTIONING) |
664 | ACPI_STA_DEVICE_UI | ACPI_STA_DEVICE_FUNCTIONING) |
644 | 665 | ||
645 | static int acpi_bus_type_and_status(ACPI_HANDLE handle, int *type, |
666 | static int acpi_bus_type_and_status(ACPI_HANDLE handle, int *type, |
646 | unsigned long long *sta) |
667 | unsigned long long *sta) |
647 | { |
668 | { |
648 | ACPI_STATUS status; |
669 | ACPI_STATUS status; |
649 | ACPI_OBJECT_TYPE acpi_type; |
670 | ACPI_OBJECT_TYPE acpi_type; |
650 | 671 | ||
651 | status = AcpiGetType(handle, &acpi_type); |
672 | status = AcpiGetType(handle, &acpi_type); |
652 | if (ACPI_FAILURE(status)) |
673 | if (ACPI_FAILURE(status)) |
653 | return -ENODEV; |
674 | return -ENODEV; |
654 | 675 | ||
655 | switch (acpi_type) |
676 | switch (acpi_type) |
656 | { |
677 | { |
657 | case ACPI_TYPE_ANY: /* for ACPI_ROOT_OBJECT */ |
678 | case ACPI_TYPE_ANY: /* for ACPI_ROOT_OBJECT */ |
658 | case ACPI_TYPE_DEVICE: |
679 | case ACPI_TYPE_DEVICE: |
659 | *type = ACPI_BUS_TYPE_DEVICE; |
680 | *type = ACPI_BUS_TYPE_DEVICE; |
660 | status = acpi_bus_get_status_handle(handle, sta); |
681 | status = acpi_bus_get_status_handle(handle, sta); |
661 | if (ACPI_FAILURE(status)) |
682 | if (ACPI_FAILURE(status)) |
662 | return -ENODEV; |
683 | return -ENODEV; |
663 | break; |
684 | break; |
664 | case ACPI_TYPE_PROCESSOR: |
685 | case ACPI_TYPE_PROCESSOR: |
665 | *type = ACPI_BUS_TYPE_PROCESSOR; |
686 | *type = ACPI_BUS_TYPE_PROCESSOR; |
666 | status = acpi_bus_get_status_handle(handle, sta); |
687 | status = acpi_bus_get_status_handle(handle, sta); |
667 | if (ACPI_FAILURE(status)) |
688 | if (ACPI_FAILURE(status)) |
668 | return -ENODEV; |
689 | return -ENODEV; |
669 | break; |
690 | break; |
670 | case ACPI_TYPE_THERMAL: |
691 | case ACPI_TYPE_THERMAL: |
671 | *type = ACPI_BUS_TYPE_THERMAL; |
692 | *type = ACPI_BUS_TYPE_THERMAL; |
672 | *sta = ACPI_STA_DEFAULT; |
693 | *sta = ACPI_STA_DEFAULT; |
673 | break; |
694 | break; |
674 | case ACPI_TYPE_POWER: |
695 | case ACPI_TYPE_POWER: |
675 | *type = ACPI_BUS_TYPE_POWER; |
696 | *type = ACPI_BUS_TYPE_POWER; |
676 | *sta = ACPI_STA_DEFAULT; |
697 | *sta = ACPI_STA_DEFAULT; |
677 | break; |
698 | break; |
678 | default: |
699 | default: |
679 | return -ENODEV; |
700 | return -ENODEV; |
680 | } |
701 | } |
681 | 702 | ||
682 | return 0; |
703 | return 0; |
683 | } |
704 | } |
684 | 705 | ||
685 | 706 | ||
686 | static ACPI_STATUS acpi_bus_check_add(ACPI_HANDLE handle, u32 lvl, |
707 | static ACPI_STATUS acpi_bus_check_add(ACPI_HANDLE handle, u32 lvl, |
687 | void *context, void **return_value) |
708 | void *context, void **return_value) |
688 | { |
709 | { |
689 | struct acpi_bus_ops *ops = context; |
710 | struct acpi_bus_ops *ops = context; |
690 | int type; |
711 | int type; |
691 | unsigned long long sta; |
712 | unsigned long long sta; |
692 | struct acpi_device *device; |
713 | struct acpi_device *device; |
693 | ACPI_STATUS status; |
714 | ACPI_STATUS status; |
694 | int result; |
715 | int result; |
695 | 716 | ||
696 | result = acpi_bus_type_and_status(handle, &type, &sta); |
717 | result = acpi_bus_type_and_status(handle, &type, &sta); |
697 | if (result) |
718 | if (result) |
698 | return AE_OK; |
719 | return AE_OK; |
699 | 720 | ||
700 | if (!(sta & ACPI_STA_DEVICE_PRESENT) && |
721 | if (!(sta & ACPI_STA_DEVICE_PRESENT) && |
701 | !(sta & ACPI_STA_DEVICE_FUNCTIONING)) |
722 | !(sta & ACPI_STA_DEVICE_FUNCTIONING)) |
702 | return AE_CTRL_DEPTH; |
723 | return AE_CTRL_DEPTH; |
703 | 724 | ||
704 | /* |
725 | /* |
705 | * We may already have an acpi_device from a previous enumeration. If |
726 | * We may already have an acpi_device from a previous enumeration. If |
706 | * so, we needn't add it again, but we may still have to start it. |
727 | * so, we needn't add it again, but we may still have to start it. |
707 | */ |
728 | */ |
708 | device = NULL; |
729 | device = NULL; |
709 | acpi_bus_get_device(handle, &device); |
730 | acpi_bus_get_device(handle, &device); |
710 | if (ops->acpi_op_add && !device) |
731 | if (ops->acpi_op_add && !device) |
711 | acpi_add_single_object(&device, handle, type, sta, ops); |
732 | acpi_add_single_object(&device, handle, type, sta, ops); |
712 | 733 | ||
713 | if (!device) |
734 | if (!device) |
714 | return AE_CTRL_DEPTH; |
735 | return AE_CTRL_DEPTH; |
715 | 736 | ||
716 | /* |
737 | /* |
717 | if (ops->acpi_op_start && !(ops->acpi_op_add)) { |
738 | if (ops->acpi_op_start && !(ops->acpi_op_add)) { |
718 | status = acpi_start_single_object(device); |
739 | status = acpi_start_single_object(device); |
719 | if (ACPI_FAILURE(status)) |
740 | if (ACPI_FAILURE(status)) |
720 | return AE_CTRL_DEPTH; |
741 | return AE_CTRL_DEPTH; |
721 | } |
742 | } |
722 | */ |
743 | */ |
723 | 744 | ||
724 | if (!*return_value) |
745 | if (!*return_value) |
725 | *return_value = device; |
746 | *return_value = device; |
726 | return AE_OK; |
747 | return AE_OK; |
727 | } |
748 | } |
728 | 749 | ||
729 | 750 | ||
730 | static int acpi_bus_scan(ACPI_HANDLE handle, struct acpi_bus_ops *ops, |
751 | static int acpi_bus_scan(ACPI_HANDLE handle, struct acpi_bus_ops *ops, |
731 | struct acpi_device **child) |
752 | struct acpi_device **child) |
732 | { |
753 | { |
733 | ACPI_STATUS status; |
754 | ACPI_STATUS status; |
734 | void *device = NULL; |
755 | void *device = NULL; |
735 | 756 | ||
736 | status = acpi_bus_check_add(handle, 0, ops, &device); |
757 | status = acpi_bus_check_add(handle, 0, ops, &device); |
737 | if (ACPI_SUCCESS(status)) |
758 | if (ACPI_SUCCESS(status)) |
738 | AcpiWalkNamespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, |
759 | AcpiWalkNamespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, |
739 | acpi_bus_check_add, NULL, ops, &device); |
760 | acpi_bus_check_add, NULL, ops, &device); |
740 | 761 | ||
741 | if (child) |
762 | if (child) |
742 | *child = device; |
763 | *child = device; |
743 | 764 | ||
744 | if (device) |
765 | if (device) |
745 | return 0; |
766 | return 0; |
746 | else |
767 | else |
747 | return -ENODEV; |
768 | return -ENODEV; |
748 | } |
769 | } |
749 | 770 | ||
750 | 771 | ||
751 | int acpi_scan() |
772 | int acpi_scan() |
752 | { |
773 | { |
753 | int err; |
774 | int err; |
754 | struct acpi_bus_ops ops; |
775 | struct acpi_bus_ops ops; |
755 | 776 | ||
756 | memset(&ops, 0, sizeof(ops)); |
777 | memset(&ops, 0, sizeof(ops)); |
757 | ops.acpi_op_add = 1; |
778 | ops.acpi_op_add = 1; |
758 | ops.acpi_op_start = 1; |
779 | ops.acpi_op_start = 1; |
759 | 780 | ||
760 | err = acpi_bus_scan(ACPI_ROOT_OBJECT, &ops, &acpi_root); |
781 | err = acpi_bus_scan(ACPI_ROOT_OBJECT, &ops, &acpi_root); |
761 | 782 | ||
762 | return err; |
783 | return err; |
763 | };> |
784 | };>> |