diff options
author | Nigel Cunningham <nigel@nigel.suspend2.net> | 2007-07-19 04:47:41 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-19 13:04:43 -0400 |
commit | 5a60d6235c8352ade8f2699e72fcdfe853730456 (patch) | |
tree | cafab638df562b912e9e2a653e5c7238816d9706 | |
parent | bd804eba1c8597cbb7cd5a5f9fe886aae16a079a (diff) |
PM: Optional beeping during resume from suspend to RAM
Add a feature allowing the user to make the system beep during a resume from
suspend to RAM, on x86_64 and i386.
This is useful for the users with broken resume from RAM, so that they can
verify if the control reaches the kernel after a wake-up event.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | arch/i386/kernel/acpi/wakeup.S | 27 | ||||
-rw-r--r-- | arch/x86_64/kernel/acpi/wakeup.S | 25 | ||||
-rw-r--r-- | include/linux/acpi.h | 1 | ||||
-rw-r--r-- | kernel/power/main.c | 23 |
4 files changed, 76 insertions, 0 deletions
diff --git a/arch/i386/kernel/acpi/wakeup.S b/arch/i386/kernel/acpi/wakeup.S index a2295a34b2c7..b4e2ec3c3928 100644 --- a/arch/i386/kernel/acpi/wakeup.S +++ b/arch/i386/kernel/acpi/wakeup.S | |||
@@ -13,6 +13,21 @@ | |||
13 | # cs = 0x1234, eip = 0x05 | 13 | # cs = 0x1234, eip = 0x05 |
14 | # | 14 | # |
15 | 15 | ||
16 | #define BEEP \ | ||
17 | inb $97, %al; \ | ||
18 | outb %al, $0x80; \ | ||
19 | movb $3, %al; \ | ||
20 | outb %al, $97; \ | ||
21 | outb %al, $0x80; \ | ||
22 | movb $-74, %al; \ | ||
23 | outb %al, $67; \ | ||
24 | outb %al, $0x80; \ | ||
25 | movb $-119, %al; \ | ||
26 | outb %al, $66; \ | ||
27 | outb %al, $0x80; \ | ||
28 | movb $15, %al; \ | ||
29 | outb %al, $66; | ||
30 | |||
16 | ALIGN | 31 | ALIGN |
17 | .align 4096 | 32 | .align 4096 |
18 | ENTRY(wakeup_start) | 33 | ENTRY(wakeup_start) |
@@ -31,6 +46,11 @@ wakeup_code: | |||
31 | movw %cs, %ax | 46 | movw %cs, %ax |
32 | movw %ax, %ds # Make ds:0 point to wakeup_start | 47 | movw %ax, %ds # Make ds:0 point to wakeup_start |
33 | movw %ax, %ss | 48 | movw %ax, %ss |
49 | |||
50 | testl $1, beep_flags - wakeup_code | ||
51 | jz 1f | ||
52 | BEEP | ||
53 | 1: | ||
34 | mov $(wakeup_stack - wakeup_code), %sp # Private stack is needed for ASUS board | 54 | mov $(wakeup_stack - wakeup_code), %sp # Private stack is needed for ASUS board |
35 | movw $0x0e00 + 'S', %fs:(0x12) | 55 | movw $0x0e00 + 'S', %fs:(0x12) |
36 | 56 | ||
@@ -88,6 +108,10 @@ wakeup_code: | |||
88 | cmpl $0x12345678, %eax | 108 | cmpl $0x12345678, %eax |
89 | jne bogus_real_magic | 109 | jne bogus_real_magic |
90 | 110 | ||
111 | testl $2, beep_flags - wakeup_code | ||
112 | jz 1f | ||
113 | BEEP | ||
114 | 1: | ||
91 | ljmpl $__KERNEL_CS,$wakeup_pmode_return | 115 | ljmpl $__KERNEL_CS,$wakeup_pmode_return |
92 | 116 | ||
93 | real_save_gdt: .word 0 | 117 | real_save_gdt: .word 0 |
@@ -98,6 +122,7 @@ real_save_cr4: .long 0 | |||
98 | real_magic: .long 0 | 122 | real_magic: .long 0 |
99 | video_mode: .long 0 | 123 | video_mode: .long 0 |
100 | video_flags: .long 0 | 124 | video_flags: .long 0 |
125 | beep_flags: .long 0 | ||
101 | real_efer_save_restore: .long 0 | 126 | real_efer_save_restore: .long 0 |
102 | real_save_efer_edx: .long 0 | 127 | real_save_efer_edx: .long 0 |
103 | real_save_efer_eax: .long 0 | 128 | real_save_efer_eax: .long 0 |
@@ -262,6 +287,8 @@ ENTRY(acpi_copy_wakeup_routine) | |||
262 | movl %edx, video_mode - wakeup_start (%eax) | 287 | movl %edx, video_mode - wakeup_start (%eax) |
263 | movl acpi_video_flags, %edx | 288 | movl acpi_video_flags, %edx |
264 | movl %edx, video_flags - wakeup_start (%eax) | 289 | movl %edx, video_flags - wakeup_start (%eax) |
290 | movl s2ram_beep, %edx | ||
291 | movl %edx, beep_flags - wakeup_start (%eax) | ||
265 | movl $0x12345678, real_magic - wakeup_start (%eax) | 292 | movl $0x12345678, real_magic - wakeup_start (%eax) |
266 | movl $0x12345678, saved_magic | 293 | movl $0x12345678, saved_magic |
267 | popl %ebx | 294 | popl %ebx |
diff --git a/arch/x86_64/kernel/acpi/wakeup.S b/arch/x86_64/kernel/acpi/wakeup.S index 8550a6ffa275..ed63d1845792 100644 --- a/arch/x86_64/kernel/acpi/wakeup.S +++ b/arch/x86_64/kernel/acpi/wakeup.S | |||
@@ -16,6 +16,21 @@ | |||
16 | # cs = 0x1234, eip = 0x05 | 16 | # cs = 0x1234, eip = 0x05 |
17 | # | 17 | # |
18 | 18 | ||
19 | #define BEEP \ | ||
20 | inb $97, %al; \ | ||
21 | outb %al, $0x80; \ | ||
22 | movb $3, %al; \ | ||
23 | outb %al, $97; \ | ||
24 | outb %al, $0x80; \ | ||
25 | movb $-74, %al; \ | ||
26 | outb %al, $67; \ | ||
27 | outb %al, $0x80; \ | ||
28 | movb $-119, %al; \ | ||
29 | outb %al, $66; \ | ||
30 | outb %al, $0x80; \ | ||
31 | movb $15, %al; \ | ||
32 | outb %al, $66; | ||
33 | |||
19 | 34 | ||
20 | ALIGN | 35 | ALIGN |
21 | .align 16 | 36 | .align 16 |
@@ -33,6 +48,13 @@ wakeup_code: | |||
33 | movw %cs, %ax | 48 | movw %cs, %ax |
34 | movw %ax, %ds # Make ds:0 point to wakeup_start | 49 | movw %ax, %ds # Make ds:0 point to wakeup_start |
35 | movw %ax, %ss | 50 | movw %ax, %ss |
51 | |||
52 | # Data segment must be set up before we can see whether to beep. | ||
53 | testl $1, beep_flags - wakeup_code | ||
54 | jz 1f | ||
55 | BEEP | ||
56 | 1: | ||
57 | |||
36 | # Private stack is needed for ASUS board | 58 | # Private stack is needed for ASUS board |
37 | mov $(wakeup_stack - wakeup_code), %sp | 59 | mov $(wakeup_stack - wakeup_code), %sp |
38 | 60 | ||
@@ -229,6 +251,7 @@ gdt_48a: | |||
229 | .long gdta - wakeup_code # gdt base (relocated in later) | 251 | .long gdta - wakeup_code # gdt base (relocated in later) |
230 | 252 | ||
231 | real_magic: .quad 0 | 253 | real_magic: .quad 0 |
254 | beep_flags: .quad 0 | ||
232 | video_mode: .quad 0 | 255 | video_mode: .quad 0 |
233 | video_flags: .quad 0 | 256 | video_flags: .quad 0 |
234 | 257 | ||
@@ -344,6 +367,8 @@ ENTRY(acpi_copy_wakeup_routine) | |||
344 | pushq %rax | 367 | pushq %rax |
345 | pushq %rdx | 368 | pushq %rdx |
346 | 369 | ||
370 | movl s2ram_beep, %edx | ||
371 | movl %edx, beep_flags - wakeup_start (,%rdi) | ||
347 | movl saved_video_mode, %edx | 372 | movl saved_video_mode, %edx |
348 | movl %edx, video_mode - wakeup_start (,%rdi) | 373 | movl %edx, video_mode - wakeup_start (,%rdi) |
349 | movl acpi_video_flags, %edx | 374 | movl acpi_video_flags, %edx |
diff --git a/include/linux/acpi.h b/include/linux/acpi.h index fccd8b548d93..c0ccdd720363 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h | |||
@@ -123,6 +123,7 @@ extern int pci_mmcfg_config_num; | |||
123 | 123 | ||
124 | extern int sbf_port; | 124 | extern int sbf_port; |
125 | extern unsigned long acpi_video_flags; | 125 | extern unsigned long acpi_video_flags; |
126 | extern unsigned long s2ram_beep; | ||
126 | 127 | ||
127 | #else /* !CONFIG_ACPI */ | 128 | #else /* !CONFIG_ACPI */ |
128 | 129 | ||
diff --git a/kernel/power/main.c b/kernel/power/main.c index 32147b57c3bf..c74a56436d8b 100644 --- a/kernel/power/main.c +++ b/kernel/power/main.c | |||
@@ -332,6 +332,27 @@ static ssize_t state_store(struct kset *kset, const char *buf, size_t n) | |||
332 | 332 | ||
333 | power_attr(state); | 333 | power_attr(state); |
334 | 334 | ||
335 | unsigned long s2ram_beep = 0; | ||
336 | |||
337 | static ssize_t s2ram_beep_show(struct kset *kset, char *buf) | ||
338 | { | ||
339 | return sprintf(buf, "%d\n", s2ram_beep); | ||
340 | } | ||
341 | |||
342 | static ssize_t | ||
343 | s2ram_beep_store(struct kset *kset, const char *buf, size_t n) | ||
344 | { | ||
345 | int val; | ||
346 | |||
347 | if (sscanf(buf, "%d", &val) > 0) { | ||
348 | s2ram_beep = val; | ||
349 | return n; | ||
350 | } | ||
351 | return -EINVAL; | ||
352 | } | ||
353 | |||
354 | power_attr(s2ram_beep); | ||
355 | |||
335 | #ifdef CONFIG_PM_TRACE | 356 | #ifdef CONFIG_PM_TRACE |
336 | int pm_trace_enabled; | 357 | int pm_trace_enabled; |
337 | 358 | ||
@@ -357,11 +378,13 @@ power_attr(pm_trace); | |||
357 | static struct attribute * g[] = { | 378 | static struct attribute * g[] = { |
358 | &state_attr.attr, | 379 | &state_attr.attr, |
359 | &pm_trace_attr.attr, | 380 | &pm_trace_attr.attr, |
381 | &s2ram_beep_attr.attr, | ||
360 | NULL, | 382 | NULL, |
361 | }; | 383 | }; |
362 | #else | 384 | #else |
363 | static struct attribute * g[] = { | 385 | static struct attribute * g[] = { |
364 | &state_attr.attr, | 386 | &state_attr.attr, |
387 | &s2ram_beep_attr.attr, | ||
365 | NULL, | 388 | NULL, |
366 | }; | 389 | }; |
367 | #endif /* CONFIG_PM_TRACE */ | 390 | #endif /* CONFIG_PM_TRACE */ |