diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/acpi/osl.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/acpi/osl.c')
-rw-r--r-- | drivers/acpi/osl.c | 1162 |
1 files changed, 1162 insertions, 0 deletions
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c new file mode 100644 index 000000000000..5a9128de6226 --- /dev/null +++ b/drivers/acpi/osl.c | |||
@@ -0,0 +1,1162 @@ | |||
1 | /* | ||
2 | * acpi_osl.c - OS-dependent functions ($Revision: 83 $) | ||
3 | * | ||
4 | * Copyright (C) 2000 Andrew Henroid | ||
5 | * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> | ||
6 | * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> | ||
7 | * | ||
8 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
23 | * | ||
24 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
25 | * | ||
26 | */ | ||
27 | |||
28 | #include <linux/config.h> | ||
29 | #include <linux/module.h> | ||
30 | #include <linux/kernel.h> | ||
31 | #include <linux/slab.h> | ||
32 | #include <linux/mm.h> | ||
33 | #include <linux/pci.h> | ||
34 | #include <linux/smp_lock.h> | ||
35 | #include <linux/interrupt.h> | ||
36 | #include <linux/kmod.h> | ||
37 | #include <linux/delay.h> | ||
38 | #include <linux/workqueue.h> | ||
39 | #include <linux/nmi.h> | ||
40 | #include <acpi/acpi.h> | ||
41 | #include <asm/io.h> | ||
42 | #include <acpi/acpi_bus.h> | ||
43 | #include <acpi/processor.h> | ||
44 | #include <asm/uaccess.h> | ||
45 | |||
46 | #include <linux/efi.h> | ||
47 | |||
48 | |||
49 | #define _COMPONENT ACPI_OS_SERVICES | ||
50 | ACPI_MODULE_NAME ("osl") | ||
51 | |||
52 | #define PREFIX "ACPI: " | ||
53 | |||
54 | struct acpi_os_dpc | ||
55 | { | ||
56 | acpi_osd_exec_callback function; | ||
57 | void *context; | ||
58 | }; | ||
59 | |||
60 | #ifdef CONFIG_ACPI_CUSTOM_DSDT | ||
61 | #include CONFIG_ACPI_CUSTOM_DSDT_FILE | ||
62 | #endif | ||
63 | |||
64 | #ifdef ENABLE_DEBUGGER | ||
65 | #include <linux/kdb.h> | ||
66 | |||
67 | /* stuff for debugger support */ | ||
68 | int acpi_in_debugger; | ||
69 | EXPORT_SYMBOL(acpi_in_debugger); | ||
70 | |||
71 | extern char line_buf[80]; | ||
72 | #endif /*ENABLE_DEBUGGER*/ | ||
73 | |||
74 | static unsigned int acpi_irq_irq; | ||
75 | static acpi_osd_handler acpi_irq_handler; | ||
76 | static void *acpi_irq_context; | ||
77 | static struct workqueue_struct *kacpid_wq; | ||
78 | |||
79 | acpi_status | ||
80 | acpi_os_initialize(void) | ||
81 | { | ||
82 | return AE_OK; | ||
83 | } | ||
84 | |||
85 | acpi_status | ||
86 | acpi_os_initialize1(void) | ||
87 | { | ||
88 | /* | ||
89 | * Initialize PCI configuration space access, as we'll need to access | ||
90 | * it while walking the namespace (bus 0 and root bridges w/ _BBNs). | ||
91 | */ | ||
92 | #ifdef CONFIG_ACPI_PCI | ||
93 | if (!raw_pci_ops) { | ||
94 | printk(KERN_ERR PREFIX "Access to PCI configuration space unavailable\n"); | ||
95 | return AE_NULL_ENTRY; | ||
96 | } | ||
97 | #endif | ||
98 | kacpid_wq = create_singlethread_workqueue("kacpid"); | ||
99 | BUG_ON(!kacpid_wq); | ||
100 | |||
101 | return AE_OK; | ||
102 | } | ||
103 | |||
104 | acpi_status | ||
105 | acpi_os_terminate(void) | ||
106 | { | ||
107 | if (acpi_irq_handler) { | ||
108 | acpi_os_remove_interrupt_handler(acpi_irq_irq, | ||
109 | acpi_irq_handler); | ||
110 | } | ||
111 | |||
112 | destroy_workqueue(kacpid_wq); | ||
113 | |||
114 | return AE_OK; | ||
115 | } | ||
116 | |||
117 | void | ||
118 | acpi_os_printf(const char *fmt,...) | ||
119 | { | ||
120 | va_list args; | ||
121 | va_start(args, fmt); | ||
122 | acpi_os_vprintf(fmt, args); | ||
123 | va_end(args); | ||
124 | } | ||
125 | EXPORT_SYMBOL(acpi_os_printf); | ||
126 | |||
127 | void | ||
128 | acpi_os_vprintf(const char *fmt, va_list args) | ||
129 | { | ||
130 | static char buffer[512]; | ||
131 | |||
132 | vsprintf(buffer, fmt, args); | ||
133 | |||
134 | #ifdef ENABLE_DEBUGGER | ||
135 | if (acpi_in_debugger) { | ||
136 | kdb_printf("%s", buffer); | ||
137 | } else { | ||
138 | printk("%s", buffer); | ||
139 | } | ||
140 | #else | ||
141 | printk("%s", buffer); | ||
142 | #endif | ||
143 | } | ||
144 | |||
145 | void * | ||
146 | acpi_os_allocate(acpi_size size) | ||
147 | { | ||
148 | return kmalloc(size, GFP_KERNEL); | ||
149 | } | ||
150 | |||
151 | void | ||
152 | acpi_os_free(void *ptr) | ||
153 | { | ||
154 | kfree(ptr); | ||
155 | } | ||
156 | EXPORT_SYMBOL(acpi_os_free); | ||
157 | |||
158 | acpi_status | ||
159 | acpi_os_get_root_pointer(u32 flags, struct acpi_pointer *addr) | ||
160 | { | ||
161 | if (efi_enabled) { | ||
162 | addr->pointer_type = ACPI_PHYSICAL_POINTER; | ||
163 | if (efi.acpi20) | ||
164 | addr->pointer.physical = | ||
165 | (acpi_physical_address) virt_to_phys(efi.acpi20); | ||
166 | else if (efi.acpi) | ||
167 | addr->pointer.physical = | ||
168 | (acpi_physical_address) virt_to_phys(efi.acpi); | ||
169 | else { | ||
170 | printk(KERN_ERR PREFIX "System description tables not found\n"); | ||
171 | return AE_NOT_FOUND; | ||
172 | } | ||
173 | } else { | ||
174 | if (ACPI_FAILURE(acpi_find_root_pointer(flags, addr))) { | ||
175 | printk(KERN_ERR PREFIX "System description tables not found\n"); | ||
176 | return AE_NOT_FOUND; | ||
177 | } | ||
178 | } | ||
179 | |||
180 | return AE_OK; | ||
181 | } | ||
182 | |||
183 | acpi_status | ||
184 | acpi_os_map_memory(acpi_physical_address phys, acpi_size size, void __iomem **virt) | ||
185 | { | ||
186 | if (efi_enabled) { | ||
187 | if (EFI_MEMORY_WB & efi_mem_attributes(phys)) { | ||
188 | *virt = (void __iomem *) phys_to_virt(phys); | ||
189 | } else { | ||
190 | *virt = ioremap(phys, size); | ||
191 | } | ||
192 | } else { | ||
193 | if (phys > ULONG_MAX) { | ||
194 | printk(KERN_ERR PREFIX "Cannot map memory that high\n"); | ||
195 | return AE_BAD_PARAMETER; | ||
196 | } | ||
197 | /* | ||
198 | * ioremap checks to ensure this is in reserved space | ||
199 | */ | ||
200 | *virt = ioremap((unsigned long) phys, size); | ||
201 | } | ||
202 | |||
203 | if (!*virt) | ||
204 | return AE_NO_MEMORY; | ||
205 | |||
206 | return AE_OK; | ||
207 | } | ||
208 | |||
209 | void | ||
210 | acpi_os_unmap_memory(void __iomem *virt, acpi_size size) | ||
211 | { | ||
212 | iounmap(virt); | ||
213 | } | ||
214 | |||
215 | #ifdef ACPI_FUTURE_USAGE | ||
216 | acpi_status | ||
217 | acpi_os_get_physical_address(void *virt, acpi_physical_address *phys) | ||
218 | { | ||
219 | if(!phys || !virt) | ||
220 | return AE_BAD_PARAMETER; | ||
221 | |||
222 | *phys = virt_to_phys(virt); | ||
223 | |||
224 | return AE_OK; | ||
225 | } | ||
226 | #endif | ||
227 | |||
228 | #define ACPI_MAX_OVERRIDE_LEN 100 | ||
229 | |||
230 | static char acpi_os_name[ACPI_MAX_OVERRIDE_LEN]; | ||
231 | |||
232 | acpi_status | ||
233 | acpi_os_predefined_override (const struct acpi_predefined_names *init_val, | ||
234 | acpi_string *new_val) | ||
235 | { | ||
236 | if (!init_val || !new_val) | ||
237 | return AE_BAD_PARAMETER; | ||
238 | |||
239 | *new_val = NULL; | ||
240 | if (!memcmp (init_val->name, "_OS_", 4) && strlen(acpi_os_name)) { | ||
241 | printk(KERN_INFO PREFIX "Overriding _OS definition to '%s'\n", | ||
242 | acpi_os_name); | ||
243 | *new_val = acpi_os_name; | ||
244 | } | ||
245 | |||
246 | return AE_OK; | ||
247 | } | ||
248 | |||
249 | acpi_status | ||
250 | acpi_os_table_override (struct acpi_table_header *existing_table, | ||
251 | struct acpi_table_header **new_table) | ||
252 | { | ||
253 | if (!existing_table || !new_table) | ||
254 | return AE_BAD_PARAMETER; | ||
255 | |||
256 | #ifdef CONFIG_ACPI_CUSTOM_DSDT | ||
257 | if (strncmp(existing_table->signature, "DSDT", 4) == 0) | ||
258 | *new_table = (struct acpi_table_header*)AmlCode; | ||
259 | else | ||
260 | *new_table = NULL; | ||
261 | #else | ||
262 | *new_table = NULL; | ||
263 | #endif | ||
264 | return AE_OK; | ||
265 | } | ||
266 | |||
267 | static irqreturn_t | ||
268 | acpi_irq(int irq, void *dev_id, struct pt_regs *regs) | ||
269 | { | ||
270 | return (*acpi_irq_handler)(acpi_irq_context) ? IRQ_HANDLED : IRQ_NONE; | ||
271 | } | ||
272 | |||
273 | acpi_status | ||
274 | acpi_os_install_interrupt_handler(u32 gsi, acpi_osd_handler handler, void *context) | ||
275 | { | ||
276 | unsigned int irq; | ||
277 | |||
278 | /* | ||
279 | * Ignore the GSI from the core, and use the value in our copy of the | ||
280 | * FADT. It may not be the same if an interrupt source override exists | ||
281 | * for the SCI. | ||
282 | */ | ||
283 | gsi = acpi_fadt.sci_int; | ||
284 | if (acpi_gsi_to_irq(gsi, &irq) < 0) { | ||
285 | printk(KERN_ERR PREFIX "SCI (ACPI GSI %d) not registered\n", | ||
286 | gsi); | ||
287 | return AE_OK; | ||
288 | } | ||
289 | |||
290 | acpi_irq_handler = handler; | ||
291 | acpi_irq_context = context; | ||
292 | if (request_irq(irq, acpi_irq, SA_SHIRQ, "acpi", acpi_irq)) { | ||
293 | printk(KERN_ERR PREFIX "SCI (IRQ%d) allocation failed\n", irq); | ||
294 | return AE_NOT_ACQUIRED; | ||
295 | } | ||
296 | acpi_irq_irq = irq; | ||
297 | |||
298 | return AE_OK; | ||
299 | } | ||
300 | |||
301 | acpi_status | ||
302 | acpi_os_remove_interrupt_handler(u32 irq, acpi_osd_handler handler) | ||
303 | { | ||
304 | if (irq) { | ||
305 | free_irq(irq, acpi_irq); | ||
306 | acpi_irq_handler = NULL; | ||
307 | acpi_irq_irq = 0; | ||
308 | } | ||
309 | |||
310 | return AE_OK; | ||
311 | } | ||
312 | |||
313 | /* | ||
314 | * Running in interpreter thread context, safe to sleep | ||
315 | */ | ||
316 | |||
317 | void | ||
318 | acpi_os_sleep(acpi_integer ms) | ||
319 | { | ||
320 | current->state = TASK_INTERRUPTIBLE; | ||
321 | schedule_timeout(((signed long) ms * HZ) / 1000); | ||
322 | } | ||
323 | EXPORT_SYMBOL(acpi_os_sleep); | ||
324 | |||
325 | void | ||
326 | acpi_os_stall(u32 us) | ||
327 | { | ||
328 | while (us) { | ||
329 | u32 delay = 1000; | ||
330 | |||
331 | if (delay > us) | ||
332 | delay = us; | ||
333 | udelay(delay); | ||
334 | touch_nmi_watchdog(); | ||
335 | us -= delay; | ||
336 | } | ||
337 | } | ||
338 | EXPORT_SYMBOL(acpi_os_stall); | ||
339 | |||
340 | /* | ||
341 | * Support ACPI 3.0 AML Timer operand | ||
342 | * Returns 64-bit free-running, monotonically increasing timer | ||
343 | * with 100ns granularity | ||
344 | */ | ||
345 | u64 | ||
346 | acpi_os_get_timer (void) | ||
347 | { | ||
348 | static u64 t; | ||
349 | |||
350 | #ifdef CONFIG_HPET | ||
351 | /* TBD: use HPET if available */ | ||
352 | #endif | ||
353 | |||
354 | #ifdef CONFIG_X86_PM_TIMER | ||
355 | /* TBD: default to PM timer if HPET was not available */ | ||
356 | #endif | ||
357 | if (!t) | ||
358 | printk(KERN_ERR PREFIX "acpi_os_get_timer() TBD\n"); | ||
359 | |||
360 | return ++t; | ||
361 | } | ||
362 | |||
363 | acpi_status | ||
364 | acpi_os_read_port( | ||
365 | acpi_io_address port, | ||
366 | u32 *value, | ||
367 | u32 width) | ||
368 | { | ||
369 | u32 dummy; | ||
370 | |||
371 | if (!value) | ||
372 | value = &dummy; | ||
373 | |||
374 | switch (width) | ||
375 | { | ||
376 | case 8: | ||
377 | *(u8*) value = inb(port); | ||
378 | break; | ||
379 | case 16: | ||
380 | *(u16*) value = inw(port); | ||
381 | break; | ||
382 | case 32: | ||
383 | *(u32*) value = inl(port); | ||
384 | break; | ||
385 | default: | ||
386 | BUG(); | ||
387 | } | ||
388 | |||
389 | return AE_OK; | ||
390 | } | ||
391 | EXPORT_SYMBOL(acpi_os_read_port); | ||
392 | |||
393 | acpi_status | ||
394 | acpi_os_write_port( | ||
395 | acpi_io_address port, | ||
396 | u32 value, | ||
397 | u32 width) | ||
398 | { | ||
399 | switch (width) | ||
400 | { | ||
401 | case 8: | ||
402 | outb(value, port); | ||
403 | break; | ||
404 | case 16: | ||
405 | outw(value, port); | ||
406 | break; | ||
407 | case 32: | ||
408 | outl(value, port); | ||
409 | break; | ||
410 | default: | ||
411 | BUG(); | ||
412 | } | ||
413 | |||
414 | return AE_OK; | ||
415 | } | ||
416 | EXPORT_SYMBOL(acpi_os_write_port); | ||
417 | |||
418 | acpi_status | ||
419 | acpi_os_read_memory( | ||
420 | acpi_physical_address phys_addr, | ||
421 | u32 *value, | ||
422 | u32 width) | ||
423 | { | ||
424 | u32 dummy; | ||
425 | void __iomem *virt_addr; | ||
426 | int iomem = 0; | ||
427 | |||
428 | if (efi_enabled) { | ||
429 | if (EFI_MEMORY_WB & efi_mem_attributes(phys_addr)) { | ||
430 | /* HACK ALERT! We can use readb/w/l on real memory too.. */ | ||
431 | virt_addr = (void __iomem *) phys_to_virt(phys_addr); | ||
432 | } else { | ||
433 | iomem = 1; | ||
434 | virt_addr = ioremap(phys_addr, width); | ||
435 | } | ||
436 | } else | ||
437 | virt_addr = (void __iomem *) phys_to_virt(phys_addr); | ||
438 | if (!value) | ||
439 | value = &dummy; | ||
440 | |||
441 | switch (width) { | ||
442 | case 8: | ||
443 | *(u8*) value = readb(virt_addr); | ||
444 | break; | ||
445 | case 16: | ||
446 | *(u16*) value = readw(virt_addr); | ||
447 | break; | ||
448 | case 32: | ||
449 | *(u32*) value = readl(virt_addr); | ||
450 | break; | ||
451 | default: | ||
452 | BUG(); | ||
453 | } | ||
454 | |||
455 | if (efi_enabled) { | ||
456 | if (iomem) | ||
457 | iounmap(virt_addr); | ||
458 | } | ||
459 | |||
460 | return AE_OK; | ||
461 | } | ||
462 | |||
463 | acpi_status | ||
464 | acpi_os_write_memory( | ||
465 | acpi_physical_address phys_addr, | ||
466 | u32 value, | ||
467 | u32 width) | ||
468 | { | ||
469 | void __iomem *virt_addr; | ||
470 | int iomem = 0; | ||
471 | |||
472 | if (efi_enabled) { | ||
473 | if (EFI_MEMORY_WB & efi_mem_attributes(phys_addr)) { | ||
474 | /* HACK ALERT! We can use writeb/w/l on real memory too */ | ||
475 | virt_addr = (void __iomem *) phys_to_virt(phys_addr); | ||
476 | } else { | ||
477 | iomem = 1; | ||
478 | virt_addr = ioremap(phys_addr, width); | ||
479 | } | ||
480 | } else | ||
481 | virt_addr = (void __iomem *) phys_to_virt(phys_addr); | ||
482 | |||
483 | switch (width) { | ||
484 | case 8: | ||
485 | writeb(value, virt_addr); | ||
486 | break; | ||
487 | case 16: | ||
488 | writew(value, virt_addr); | ||
489 | break; | ||
490 | case 32: | ||
491 | writel(value, virt_addr); | ||
492 | break; | ||
493 | default: | ||
494 | BUG(); | ||
495 | } | ||
496 | |||
497 | if (iomem) | ||
498 | iounmap(virt_addr); | ||
499 | |||
500 | return AE_OK; | ||
501 | } | ||
502 | |||
503 | #ifdef CONFIG_ACPI_PCI | ||
504 | |||
505 | acpi_status | ||
506 | acpi_os_read_pci_configuration (struct acpi_pci_id *pci_id, u32 reg, void *value, u32 width) | ||
507 | { | ||
508 | int result, size; | ||
509 | |||
510 | if (!value) | ||
511 | return AE_BAD_PARAMETER; | ||
512 | |||
513 | switch (width) { | ||
514 | case 8: | ||
515 | size = 1; | ||
516 | break; | ||
517 | case 16: | ||
518 | size = 2; | ||
519 | break; | ||
520 | case 32: | ||
521 | size = 4; | ||
522 | break; | ||
523 | default: | ||
524 | return AE_ERROR; | ||
525 | } | ||
526 | |||
527 | BUG_ON(!raw_pci_ops); | ||
528 | |||
529 | result = raw_pci_ops->read(pci_id->segment, pci_id->bus, | ||
530 | PCI_DEVFN(pci_id->device, pci_id->function), | ||
531 | reg, size, value); | ||
532 | |||
533 | return (result ? AE_ERROR : AE_OK); | ||
534 | } | ||
535 | EXPORT_SYMBOL(acpi_os_read_pci_configuration); | ||
536 | |||
537 | acpi_status | ||
538 | acpi_os_write_pci_configuration (struct acpi_pci_id *pci_id, u32 reg, acpi_integer value, u32 width) | ||
539 | { | ||
540 | int result, size; | ||
541 | |||
542 | switch (width) { | ||
543 | case 8: | ||
544 | size = 1; | ||
545 | break; | ||
546 | case 16: | ||
547 | size = 2; | ||
548 | break; | ||
549 | case 32: | ||
550 | size = 4; | ||
551 | break; | ||
552 | default: | ||
553 | return AE_ERROR; | ||
554 | } | ||
555 | |||
556 | BUG_ON(!raw_pci_ops); | ||
557 | |||
558 | result = raw_pci_ops->write(pci_id->segment, pci_id->bus, | ||
559 | PCI_DEVFN(pci_id->device, pci_id->function), | ||
560 | reg, size, value); | ||
561 | |||
562 | return (result ? AE_ERROR : AE_OK); | ||
563 | } | ||
564 | |||
565 | /* TODO: Change code to take advantage of driver model more */ | ||
566 | static void | ||
567 | acpi_os_derive_pci_id_2 ( | ||
568 | acpi_handle rhandle, /* upper bound */ | ||
569 | acpi_handle chandle, /* current node */ | ||
570 | struct acpi_pci_id **id, | ||
571 | int *is_bridge, | ||
572 | u8 *bus_number) | ||
573 | { | ||
574 | acpi_handle handle; | ||
575 | struct acpi_pci_id *pci_id = *id; | ||
576 | acpi_status status; | ||
577 | unsigned long temp; | ||
578 | acpi_object_type type; | ||
579 | u8 tu8; | ||
580 | |||
581 | acpi_get_parent(chandle, &handle); | ||
582 | if (handle != rhandle) { | ||
583 | acpi_os_derive_pci_id_2(rhandle, handle, &pci_id, is_bridge, bus_number); | ||
584 | |||
585 | status = acpi_get_type(handle, &type); | ||
586 | if ( (ACPI_FAILURE(status)) || (type != ACPI_TYPE_DEVICE) ) | ||
587 | return; | ||
588 | |||
589 | status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &temp); | ||
590 | if (ACPI_SUCCESS(status)) { | ||
591 | pci_id->device = ACPI_HIWORD (ACPI_LODWORD (temp)); | ||
592 | pci_id->function = ACPI_LOWORD (ACPI_LODWORD (temp)); | ||
593 | |||
594 | if (*is_bridge) | ||
595 | pci_id->bus = *bus_number; | ||
596 | |||
597 | /* any nicer way to get bus number of bridge ? */ | ||
598 | status = acpi_os_read_pci_configuration(pci_id, 0x0e, &tu8, 8); | ||
599 | if (ACPI_SUCCESS(status) && | ||
600 | ((tu8 & 0x7f) == 1 || (tu8 & 0x7f) == 2)) { | ||
601 | status = acpi_os_read_pci_configuration(pci_id, 0x18, &tu8, 8); | ||
602 | if (!ACPI_SUCCESS(status)) { | ||
603 | /* Certainly broken... FIX ME */ | ||
604 | return; | ||
605 | } | ||
606 | *is_bridge = 1; | ||
607 | pci_id->bus = tu8; | ||
608 | status = acpi_os_read_pci_configuration(pci_id, 0x19, &tu8, 8); | ||
609 | if (ACPI_SUCCESS(status)) { | ||
610 | *bus_number = tu8; | ||
611 | } | ||
612 | } else | ||
613 | *is_bridge = 0; | ||
614 | } | ||
615 | } | ||
616 | } | ||
617 | |||
618 | void | ||
619 | acpi_os_derive_pci_id ( | ||
620 | acpi_handle rhandle, /* upper bound */ | ||
621 | acpi_handle chandle, /* current node */ | ||
622 | struct acpi_pci_id **id) | ||
623 | { | ||
624 | int is_bridge = 1; | ||
625 | u8 bus_number = (*id)->bus; | ||
626 | |||
627 | acpi_os_derive_pci_id_2(rhandle, chandle, id, &is_bridge, &bus_number); | ||
628 | } | ||
629 | |||
630 | #else /*!CONFIG_ACPI_PCI*/ | ||
631 | |||
632 | acpi_status | ||
633 | acpi_os_write_pci_configuration ( | ||
634 | struct acpi_pci_id *pci_id, | ||
635 | u32 reg, | ||
636 | acpi_integer value, | ||
637 | u32 width) | ||
638 | { | ||
639 | return AE_SUPPORT; | ||
640 | } | ||
641 | |||
642 | acpi_status | ||
643 | acpi_os_read_pci_configuration ( | ||
644 | struct acpi_pci_id *pci_id, | ||
645 | u32 reg, | ||
646 | void *value, | ||
647 | u32 width) | ||
648 | { | ||
649 | return AE_SUPPORT; | ||
650 | } | ||
651 | |||
652 | void | ||
653 | acpi_os_derive_pci_id ( | ||
654 | acpi_handle rhandle, /* upper bound */ | ||
655 | acpi_handle chandle, /* current node */ | ||
656 | struct acpi_pci_id **id) | ||
657 | { | ||
658 | } | ||
659 | |||
660 | #endif /*CONFIG_ACPI_PCI*/ | ||
661 | |||
662 | static void | ||
663 | acpi_os_execute_deferred ( | ||
664 | void *context) | ||
665 | { | ||
666 | struct acpi_os_dpc *dpc = NULL; | ||
667 | |||
668 | ACPI_FUNCTION_TRACE ("os_execute_deferred"); | ||
669 | |||
670 | dpc = (struct acpi_os_dpc *) context; | ||
671 | if (!dpc) { | ||
672 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid (NULL) context.\n")); | ||
673 | return_VOID; | ||
674 | } | ||
675 | |||
676 | dpc->function(dpc->context); | ||
677 | |||
678 | kfree(dpc); | ||
679 | |||
680 | return_VOID; | ||
681 | } | ||
682 | |||
683 | acpi_status | ||
684 | acpi_os_queue_for_execution( | ||
685 | u32 priority, | ||
686 | acpi_osd_exec_callback function, | ||
687 | void *context) | ||
688 | { | ||
689 | acpi_status status = AE_OK; | ||
690 | struct acpi_os_dpc *dpc; | ||
691 | struct work_struct *task; | ||
692 | |||
693 | ACPI_FUNCTION_TRACE ("os_queue_for_execution"); | ||
694 | |||
695 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Scheduling function [%p(%p)] for deferred execution.\n", function, context)); | ||
696 | |||
697 | if (!function) | ||
698 | return_ACPI_STATUS (AE_BAD_PARAMETER); | ||
699 | |||
700 | /* | ||
701 | * Allocate/initialize DPC structure. Note that this memory will be | ||
702 | * freed by the callee. The kernel handles the tq_struct list in a | ||
703 | * way that allows us to also free its memory inside the callee. | ||
704 | * Because we may want to schedule several tasks with different | ||
705 | * parameters we can't use the approach some kernel code uses of | ||
706 | * having a static tq_struct. | ||
707 | * We can save time and code by allocating the DPC and tq_structs | ||
708 | * from the same memory. | ||
709 | */ | ||
710 | |||
711 | dpc = kmalloc(sizeof(struct acpi_os_dpc)+sizeof(struct work_struct), GFP_ATOMIC); | ||
712 | if (!dpc) | ||
713 | return_ACPI_STATUS (AE_NO_MEMORY); | ||
714 | |||
715 | dpc->function = function; | ||
716 | dpc->context = context; | ||
717 | |||
718 | task = (void *)(dpc+1); | ||
719 | INIT_WORK(task, acpi_os_execute_deferred, (void*)dpc); | ||
720 | |||
721 | if (!queue_work(kacpid_wq, task)) { | ||
722 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Call to queue_work() failed.\n")); | ||
723 | kfree(dpc); | ||
724 | status = AE_ERROR; | ||
725 | } | ||
726 | |||
727 | return_ACPI_STATUS (status); | ||
728 | } | ||
729 | EXPORT_SYMBOL(acpi_os_queue_for_execution); | ||
730 | |||
731 | void | ||
732 | acpi_os_wait_events_complete( | ||
733 | void *context) | ||
734 | { | ||
735 | flush_workqueue(kacpid_wq); | ||
736 | } | ||
737 | EXPORT_SYMBOL(acpi_os_wait_events_complete); | ||
738 | |||
739 | /* | ||
740 | * Allocate the memory for a spinlock and initialize it. | ||
741 | */ | ||
742 | acpi_status | ||
743 | acpi_os_create_lock ( | ||
744 | acpi_handle *out_handle) | ||
745 | { | ||
746 | spinlock_t *lock_ptr; | ||
747 | |||
748 | ACPI_FUNCTION_TRACE ("os_create_lock"); | ||
749 | |||
750 | lock_ptr = acpi_os_allocate(sizeof(spinlock_t)); | ||
751 | |||
752 | spin_lock_init(lock_ptr); | ||
753 | |||
754 | ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Creating spinlock[%p].\n", lock_ptr)); | ||
755 | |||
756 | *out_handle = lock_ptr; | ||
757 | |||
758 | return_ACPI_STATUS (AE_OK); | ||
759 | } | ||
760 | |||
761 | |||
762 | /* | ||
763 | * Deallocate the memory for a spinlock. | ||
764 | */ | ||
765 | void | ||
766 | acpi_os_delete_lock ( | ||
767 | acpi_handle handle) | ||
768 | { | ||
769 | ACPI_FUNCTION_TRACE ("os_create_lock"); | ||
770 | |||
771 | ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Deleting spinlock[%p].\n", handle)); | ||
772 | |||
773 | acpi_os_free(handle); | ||
774 | |||
775 | return_VOID; | ||
776 | } | ||
777 | |||
778 | /* | ||
779 | * Acquire a spinlock. | ||
780 | * | ||
781 | * handle is a pointer to the spinlock_t. | ||
782 | * flags is *not* the result of save_flags - it is an ACPI-specific flag variable | ||
783 | * that indicates whether we are at interrupt level. | ||
784 | */ | ||
785 | void | ||
786 | acpi_os_acquire_lock ( | ||
787 | acpi_handle handle, | ||
788 | u32 flags) | ||
789 | { | ||
790 | ACPI_FUNCTION_TRACE ("os_acquire_lock"); | ||
791 | |||
792 | ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Acquiring spinlock[%p] from %s level\n", handle, | ||
793 | ((flags & ACPI_NOT_ISR) ? "non-interrupt" : "interrupt"))); | ||
794 | |||
795 | if (flags & ACPI_NOT_ISR) | ||
796 | ACPI_DISABLE_IRQS(); | ||
797 | |||
798 | spin_lock((spinlock_t *)handle); | ||
799 | |||
800 | return_VOID; | ||
801 | } | ||
802 | |||
803 | |||
804 | /* | ||
805 | * Release a spinlock. See above. | ||
806 | */ | ||
807 | void | ||
808 | acpi_os_release_lock ( | ||
809 | acpi_handle handle, | ||
810 | u32 flags) | ||
811 | { | ||
812 | ACPI_FUNCTION_TRACE ("os_release_lock"); | ||
813 | |||
814 | ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Releasing spinlock[%p] from %s level\n", handle, | ||
815 | ((flags & ACPI_NOT_ISR) ? "non-interrupt" : "interrupt"))); | ||
816 | |||
817 | spin_unlock((spinlock_t *)handle); | ||
818 | |||
819 | if (flags & ACPI_NOT_ISR) | ||
820 | ACPI_ENABLE_IRQS(); | ||
821 | |||
822 | return_VOID; | ||
823 | } | ||
824 | |||
825 | |||
826 | acpi_status | ||
827 | acpi_os_create_semaphore( | ||
828 | u32 max_units, | ||
829 | u32 initial_units, | ||
830 | acpi_handle *handle) | ||
831 | { | ||
832 | struct semaphore *sem = NULL; | ||
833 | |||
834 | ACPI_FUNCTION_TRACE ("os_create_semaphore"); | ||
835 | |||
836 | sem = acpi_os_allocate(sizeof(struct semaphore)); | ||
837 | if (!sem) | ||
838 | return_ACPI_STATUS (AE_NO_MEMORY); | ||
839 | memset(sem, 0, sizeof(struct semaphore)); | ||
840 | |||
841 | sema_init(sem, initial_units); | ||
842 | |||
843 | *handle = (acpi_handle*)sem; | ||
844 | |||
845 | ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Creating semaphore[%p|%d].\n", *handle, initial_units)); | ||
846 | |||
847 | return_ACPI_STATUS (AE_OK); | ||
848 | } | ||
849 | EXPORT_SYMBOL(acpi_os_create_semaphore); | ||
850 | |||
851 | |||
852 | /* | ||
853 | * TODO: A better way to delete semaphores? Linux doesn't have a | ||
854 | * 'delete_semaphore()' function -- may result in an invalid | ||
855 | * pointer dereference for non-synchronized consumers. Should | ||
856 | * we at least check for blocked threads and signal/cancel them? | ||
857 | */ | ||
858 | |||
859 | acpi_status | ||
860 | acpi_os_delete_semaphore( | ||
861 | acpi_handle handle) | ||
862 | { | ||
863 | struct semaphore *sem = (struct semaphore*) handle; | ||
864 | |||
865 | ACPI_FUNCTION_TRACE ("os_delete_semaphore"); | ||
866 | |||
867 | if (!sem) | ||
868 | return_ACPI_STATUS (AE_BAD_PARAMETER); | ||
869 | |||
870 | ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Deleting semaphore[%p].\n", handle)); | ||
871 | |||
872 | acpi_os_free(sem); sem = NULL; | ||
873 | |||
874 | return_ACPI_STATUS (AE_OK); | ||
875 | } | ||
876 | EXPORT_SYMBOL(acpi_os_delete_semaphore); | ||
877 | |||
878 | |||
879 | /* | ||
880 | * TODO: The kernel doesn't have a 'down_timeout' function -- had to | ||
881 | * improvise. The process is to sleep for one scheduler quantum | ||
882 | * until the semaphore becomes available. Downside is that this | ||
883 | * may result in starvation for timeout-based waits when there's | ||
884 | * lots of semaphore activity. | ||
885 | * | ||
886 | * TODO: Support for units > 1? | ||
887 | */ | ||
888 | acpi_status | ||
889 | acpi_os_wait_semaphore( | ||
890 | acpi_handle handle, | ||
891 | u32 units, | ||
892 | u16 timeout) | ||
893 | { | ||
894 | acpi_status status = AE_OK; | ||
895 | struct semaphore *sem = (struct semaphore*)handle; | ||
896 | int ret = 0; | ||
897 | |||
898 | ACPI_FUNCTION_TRACE ("os_wait_semaphore"); | ||
899 | |||
900 | if (!sem || (units < 1)) | ||
901 | return_ACPI_STATUS (AE_BAD_PARAMETER); | ||
902 | |||
903 | if (units > 1) | ||
904 | return_ACPI_STATUS (AE_SUPPORT); | ||
905 | |||
906 | ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Waiting for semaphore[%p|%d|%d]\n", handle, units, timeout)); | ||
907 | |||
908 | if (in_atomic()) | ||
909 | timeout = 0; | ||
910 | |||
911 | switch (timeout) | ||
912 | { | ||
913 | /* | ||
914 | * No Wait: | ||
915 | * -------- | ||
916 | * A zero timeout value indicates that we shouldn't wait - just | ||
917 | * acquire the semaphore if available otherwise return AE_TIME | ||
918 | * (a.k.a. 'would block'). | ||
919 | */ | ||
920 | case 0: | ||
921 | if(down_trylock(sem)) | ||
922 | status = AE_TIME; | ||
923 | break; | ||
924 | |||
925 | /* | ||
926 | * Wait Indefinitely: | ||
927 | * ------------------ | ||
928 | */ | ||
929 | case ACPI_WAIT_FOREVER: | ||
930 | down(sem); | ||
931 | break; | ||
932 | |||
933 | /* | ||
934 | * Wait w/ Timeout: | ||
935 | * ---------------- | ||
936 | */ | ||
937 | default: | ||
938 | // TODO: A better timeout algorithm? | ||
939 | { | ||
940 | int i = 0; | ||
941 | static const int quantum_ms = 1000/HZ; | ||
942 | |||
943 | ret = down_trylock(sem); | ||
944 | for (i = timeout; (i > 0 && ret < 0); i -= quantum_ms) { | ||
945 | current->state = TASK_INTERRUPTIBLE; | ||
946 | schedule_timeout(1); | ||
947 | ret = down_trylock(sem); | ||
948 | } | ||
949 | |||
950 | if (ret != 0) | ||
951 | status = AE_TIME; | ||
952 | } | ||
953 | break; | ||
954 | } | ||
955 | |||
956 | if (ACPI_FAILURE(status)) { | ||
957 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Failed to acquire semaphore[%p|%d|%d], %s\n", | ||
958 | handle, units, timeout, acpi_format_exception(status))); | ||
959 | } | ||
960 | else { | ||
961 | ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Acquired semaphore[%p|%d|%d]\n", handle, units, timeout)); | ||
962 | } | ||
963 | |||
964 | return_ACPI_STATUS (status); | ||
965 | } | ||
966 | EXPORT_SYMBOL(acpi_os_wait_semaphore); | ||
967 | |||
968 | |||
969 | /* | ||
970 | * TODO: Support for units > 1? | ||
971 | */ | ||
972 | acpi_status | ||
973 | acpi_os_signal_semaphore( | ||
974 | acpi_handle handle, | ||
975 | u32 units) | ||
976 | { | ||
977 | struct semaphore *sem = (struct semaphore *) handle; | ||
978 | |||
979 | ACPI_FUNCTION_TRACE ("os_signal_semaphore"); | ||
980 | |||
981 | if (!sem || (units < 1)) | ||
982 | return_ACPI_STATUS (AE_BAD_PARAMETER); | ||
983 | |||
984 | if (units > 1) | ||
985 | return_ACPI_STATUS (AE_SUPPORT); | ||
986 | |||
987 | ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Signaling semaphore[%p|%d]\n", handle, units)); | ||
988 | |||
989 | up(sem); | ||
990 | |||
991 | return_ACPI_STATUS (AE_OK); | ||
992 | } | ||
993 | EXPORT_SYMBOL(acpi_os_signal_semaphore); | ||
994 | |||
995 | #ifdef ACPI_FUTURE_USAGE | ||
996 | u32 | ||
997 | acpi_os_get_line(char *buffer) | ||
998 | { | ||
999 | |||
1000 | #ifdef ENABLE_DEBUGGER | ||
1001 | if (acpi_in_debugger) { | ||
1002 | u32 chars; | ||
1003 | |||
1004 | kdb_read(buffer, sizeof(line_buf)); | ||
1005 | |||
1006 | /* remove the CR kdb includes */ | ||
1007 | chars = strlen(buffer) - 1; | ||
1008 | buffer[chars] = '\0'; | ||
1009 | } | ||
1010 | #endif | ||
1011 | |||
1012 | return 0; | ||
1013 | } | ||
1014 | #endif /* ACPI_FUTURE_USAGE */ | ||
1015 | |||
1016 | /* Assumes no unreadable holes inbetween */ | ||
1017 | u8 | ||
1018 | acpi_os_readable(void *ptr, acpi_size len) | ||
1019 | { | ||
1020 | #if defined(__i386__) || defined(__x86_64__) | ||
1021 | char tmp; | ||
1022 | return !__get_user(tmp, (char __user *)ptr) && !__get_user(tmp, (char __user *)ptr + len - 1); | ||
1023 | #endif | ||
1024 | return 1; | ||
1025 | } | ||
1026 | |||
1027 | #ifdef ACPI_FUTURE_USAGE | ||
1028 | u8 | ||
1029 | acpi_os_writable(void *ptr, acpi_size len) | ||
1030 | { | ||
1031 | /* could do dummy write (racy) or a kernel page table lookup. | ||
1032 | The later may be difficult at early boot when kmap doesn't work yet. */ | ||
1033 | return 1; | ||
1034 | } | ||
1035 | #endif | ||
1036 | |||
1037 | u32 | ||
1038 | acpi_os_get_thread_id (void) | ||
1039 | { | ||
1040 | if (!in_atomic()) | ||
1041 | return current->pid; | ||
1042 | |||
1043 | return 0; | ||
1044 | } | ||
1045 | |||
1046 | acpi_status | ||
1047 | acpi_os_signal ( | ||
1048 | u32 function, | ||
1049 | void *info) | ||
1050 | { | ||
1051 | switch (function) | ||
1052 | { | ||
1053 | case ACPI_SIGNAL_FATAL: | ||
1054 | printk(KERN_ERR PREFIX "Fatal opcode executed\n"); | ||
1055 | break; | ||
1056 | case ACPI_SIGNAL_BREAKPOINT: | ||
1057 | /* | ||
1058 | * AML Breakpoint | ||
1059 | * ACPI spec. says to treat it as a NOP unless | ||
1060 | * you are debugging. So if/when we integrate | ||
1061 | * AML debugger into the kernel debugger its | ||
1062 | * hook will go here. But until then it is | ||
1063 | * not useful to print anything on breakpoints. | ||
1064 | */ | ||
1065 | break; | ||
1066 | default: | ||
1067 | break; | ||
1068 | } | ||
1069 | |||
1070 | return AE_OK; | ||
1071 | } | ||
1072 | EXPORT_SYMBOL(acpi_os_signal); | ||
1073 | |||
1074 | static int __init | ||
1075 | acpi_os_name_setup(char *str) | ||
1076 | { | ||
1077 | char *p = acpi_os_name; | ||
1078 | int count = ACPI_MAX_OVERRIDE_LEN-1; | ||
1079 | |||
1080 | if (!str || !*str) | ||
1081 | return 0; | ||
1082 | |||
1083 | for (; count-- && str && *str; str++) { | ||
1084 | if (isalnum(*str) || *str == ' ' || *str == ':') | ||
1085 | *p++ = *str; | ||
1086 | else if (*str == '\'' || *str == '"') | ||
1087 | continue; | ||
1088 | else | ||
1089 | break; | ||
1090 | } | ||
1091 | *p = 0; | ||
1092 | |||
1093 | return 1; | ||
1094 | |||
1095 | } | ||
1096 | |||
1097 | __setup("acpi_os_name=", acpi_os_name_setup); | ||
1098 | |||
1099 | /* | ||
1100 | * _OSI control | ||
1101 | * empty string disables _OSI | ||
1102 | * TBD additional string adds to _OSI | ||
1103 | */ | ||
1104 | static int __init | ||
1105 | acpi_osi_setup(char *str) | ||
1106 | { | ||
1107 | if (str == NULL || *str == '\0') { | ||
1108 | printk(KERN_INFO PREFIX "_OSI method disabled\n"); | ||
1109 | acpi_gbl_create_osi_method = FALSE; | ||
1110 | } else | ||
1111 | { | ||
1112 | /* TBD */ | ||
1113 | printk(KERN_ERR PREFIX "_OSI additional string ignored -- %s\n", str); | ||
1114 | } | ||
1115 | |||
1116 | return 1; | ||
1117 | } | ||
1118 | |||
1119 | __setup("acpi_osi=", acpi_osi_setup); | ||
1120 | |||
1121 | /* enable serialization to combat AE_ALREADY_EXISTS errors */ | ||
1122 | static int __init | ||
1123 | acpi_serialize_setup(char *str) | ||
1124 | { | ||
1125 | printk(KERN_INFO PREFIX "serialize enabled\n"); | ||
1126 | |||
1127 | acpi_gbl_all_methods_serialized = TRUE; | ||
1128 | |||
1129 | return 1; | ||
1130 | } | ||
1131 | |||
1132 | __setup("acpi_serialize", acpi_serialize_setup); | ||
1133 | |||
1134 | /* | ||
1135 | * Wake and Run-Time GPES are expected to be separate. | ||
1136 | * We disable wake-GPEs at run-time to prevent spurious | ||
1137 | * interrupts. | ||
1138 | * | ||
1139 | * However, if a system exists that shares Wake and | ||
1140 | * Run-time events on the same GPE this flag is available | ||
1141 | * to tell Linux to keep the wake-time GPEs enabled at run-time. | ||
1142 | */ | ||
1143 | static int __init | ||
1144 | acpi_wake_gpes_always_on_setup(char *str) | ||
1145 | { | ||
1146 | printk(KERN_INFO PREFIX "wake GPEs not disabled\n"); | ||
1147 | |||
1148 | acpi_gbl_leave_wake_gpes_disabled = FALSE; | ||
1149 | |||
1150 | return 1; | ||
1151 | } | ||
1152 | |||
1153 | __setup("acpi_wake_gpes_always_on", acpi_wake_gpes_always_on_setup); | ||
1154 | |||
1155 | /* | ||
1156 | * max_cstate is defined in the base kernel so modules can | ||
1157 | * change it w/o depending on the state of the processor module. | ||
1158 | */ | ||
1159 | unsigned int max_cstate = ACPI_PROCESSOR_MAX_POWER; | ||
1160 | |||
1161 | |||
1162 | EXPORT_SYMBOL(max_cstate); | ||