Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * sleep.c - x86-specific ACPI sleep support. | |
3 | * | |
4 | * Copyright (C) 2001-2003 Patrick Mochel | |
5 | * Copyright (C) 2001-2003 Pavel Machek <pavel@suse.cz> | |
6 | */ | |
7 | ||
8 | #include <linux/acpi.h> | |
9 | #include <linux/bootmem.h> | |
0f8133a8 | 10 | #include <linux/dmi.h> |
55b2355e SL |
11 | #include <linux/cpumask.h> |
12 | ||
1da177e4 | 13 | #include <asm/smp.h> |
1da177e4 LT |
14 | |
15 | /* address in low memory of the wakeup routine. */ | |
16 | unsigned long acpi_wakeup_address = 0; | |
77afcf78 | 17 | unsigned long acpi_realmode_flags; |
1da177e4 LT |
18 | extern char wakeup_start, wakeup_end; |
19 | ||
1da177e4 LT |
20 | extern unsigned long FASTCALL(acpi_copy_wakeup_routine(unsigned long)); |
21 | ||
1da177e4 LT |
22 | /** |
23 | * acpi_save_state_mem - save kernel state | |
24 | * | |
25 | * Create an identity mapped page table and copy the wakeup routine to | |
26 | * low memory. | |
27 | */ | |
4be44fcd | 28 | int acpi_save_state_mem(void) |
1da177e4 LT |
29 | { |
30 | if (!acpi_wakeup_address) | |
31 | return 1; | |
4be44fcd LB |
32 | memcpy((void *)acpi_wakeup_address, &wakeup_start, |
33 | &wakeup_end - &wakeup_start); | |
1da177e4 LT |
34 | acpi_copy_wakeup_routine(acpi_wakeup_address); |
35 | ||
36 | return 0; | |
37 | } | |
38 | ||
39 | /* | |
40 | * acpi_restore_state - undo effects of acpi_save_state_mem | |
41 | */ | |
4be44fcd | 42 | void acpi_restore_state_mem(void) |
1da177e4 | 43 | { |
1da177e4 LT |
44 | } |
45 | ||
46 | /** | |
47 | * acpi_reserve_bootmem - do _very_ early ACPI initialisation | |
48 | * | |
49 | * We allocate a page from the first 1MB of memory for the wakeup | |
50 | * routine for when we come back from a sleep state. The | |
51 | * runtime allocator allows specification of <16MB pages, but not | |
52 | * <1MB pages. | |
53 | */ | |
54 | void __init acpi_reserve_bootmem(void) | |
55 | { | |
56 | if ((&wakeup_end - &wakeup_start) > PAGE_SIZE) { | |
4be44fcd LB |
57 | printk(KERN_ERR |
58 | "ACPI: Wakeup code way too big, S3 disabled.\n"); | |
1da177e4 LT |
59 | return; |
60 | } | |
61 | ||
62 | acpi_wakeup_address = (unsigned long)alloc_bootmem_low(PAGE_SIZE); | |
63 | if (!acpi_wakeup_address) | |
64 | printk(KERN_ERR "ACPI: Cannot allocate lowmem, S3 disabled.\n"); | |
65 | } | |
66 | ||
67 | static int __init acpi_sleep_setup(char *str) | |
68 | { | |
69 | while ((str != NULL) && (*str != '\0')) { | |
70 | if (strncmp(str, "s3_bios", 7) == 0) | |
77afcf78 | 71 | acpi_realmode_flags |= 1; |
1da177e4 | 72 | if (strncmp(str, "s3_mode", 7) == 0) |
77afcf78 PM |
73 | acpi_realmode_flags |= 2; |
74 | if (strncmp(str, "s3_beep", 7) == 0) | |
75 | acpi_realmode_flags |= 4; | |
1da177e4 LT |
76 | str = strchr(str, ','); |
77 | if (str != NULL) | |
78 | str += strspn(str, ", \t"); | |
79 | } | |
80 | return 1; | |
81 | } | |
82 | ||
1da177e4 | 83 | __setup("acpi_sleep=", acpi_sleep_setup); |
0f8133a8 | 84 | |
77afcf78 PM |
85 | /* Ouch, we want to delete this. We already have better version in userspace, in |
86 | s2ram from suspend.sf.net project */ | |
0f8133a8 AP |
87 | static __init int reset_videomode_after_s3(struct dmi_system_id *d) |
88 | { | |
77afcf78 | 89 | acpi_realmode_flags |= 2; |
0f8133a8 AP |
90 | return 0; |
91 | } | |
92 | ||
93 | static __initdata struct dmi_system_id acpisleep_dmi_table[] = { | |
4be44fcd LB |
94 | { /* Reset video mode after returning from ACPI S3 sleep */ |
95 | .callback = reset_videomode_after_s3, | |
96 | .ident = "Toshiba Satellite 4030cdt", | |
97 | .matches = { | |
98 | DMI_MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"), | |
99 | }, | |
100 | }, | |
101 | {} | |
0f8133a8 AP |
102 | }; |
103 | ||
104 | static int __init acpisleep_dmi_init(void) | |
105 | { | |
106 | dmi_check_system(acpisleep_dmi_table); | |
107 | return 0; | |
108 | } | |
109 | ||
110 | core_initcall(acpisleep_dmi_init); |