sleep.c 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  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. #include <linux/acpi.h>
  8. #include <linux/bootmem.h>
  9. #include <linux/dmi.h>
  10. #include <linux/cpumask.h>
  11. #include <asm/smp.h>
  12. /* address in low memory of the wakeup routine. */
  13. unsigned long acpi_wakeup_address = 0;
  14. unsigned long acpi_video_flags;
  15. extern char wakeup_start, wakeup_end;
  16. extern unsigned long FASTCALL(acpi_copy_wakeup_routine(unsigned long));
  17. /**
  18. * acpi_save_state_mem - save kernel state
  19. *
  20. * Create an identity mapped page table and copy the wakeup routine to
  21. * low memory.
  22. */
  23. int acpi_save_state_mem(void)
  24. {
  25. if (!acpi_wakeup_address)
  26. return 1;
  27. memcpy((void *)acpi_wakeup_address, &wakeup_start,
  28. &wakeup_end - &wakeup_start);
  29. acpi_copy_wakeup_routine(acpi_wakeup_address);
  30. return 0;
  31. }
  32. /*
  33. * acpi_restore_state - undo effects of acpi_save_state_mem
  34. */
  35. void acpi_restore_state_mem(void)
  36. {
  37. }
  38. /**
  39. * acpi_reserve_bootmem - do _very_ early ACPI initialisation
  40. *
  41. * We allocate a page from the first 1MB of memory for the wakeup
  42. * routine for when we come back from a sleep state. The
  43. * runtime allocator allows specification of <16MB pages, but not
  44. * <1MB pages.
  45. */
  46. void __init acpi_reserve_bootmem(void)
  47. {
  48. if ((&wakeup_end - &wakeup_start) > PAGE_SIZE) {
  49. printk(KERN_ERR
  50. "ACPI: Wakeup code way too big, S3 disabled.\n");
  51. return;
  52. }
  53. acpi_wakeup_address = (unsigned long)alloc_bootmem_low(PAGE_SIZE);
  54. if (!acpi_wakeup_address)
  55. printk(KERN_ERR "ACPI: Cannot allocate lowmem, S3 disabled.\n");
  56. }
  57. static int __init acpi_sleep_setup(char *str)
  58. {
  59. while ((str != NULL) && (*str != '\0')) {
  60. if (strncmp(str, "s3_bios", 7) == 0)
  61. acpi_video_flags = 1;
  62. if (strncmp(str, "s3_mode", 7) == 0)
  63. acpi_video_flags |= 2;
  64. str = strchr(str, ',');
  65. if (str != NULL)
  66. str += strspn(str, ", \t");
  67. }
  68. return 1;
  69. }
  70. __setup("acpi_sleep=", acpi_sleep_setup);
  71. static __init int reset_videomode_after_s3(struct dmi_system_id *d)
  72. {
  73. acpi_video_flags |= 2;
  74. return 0;
  75. }
  76. static __initdata struct dmi_system_id acpisleep_dmi_table[] = {
  77. { /* Reset video mode after returning from ACPI S3 sleep */
  78. .callback = reset_videomode_after_s3,
  79. .ident = "Toshiba Satellite 4030cdt",
  80. .matches = {
  81. DMI_MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"),
  82. },
  83. },
  84. {}
  85. };
  86. static int __init acpisleep_dmi_init(void)
  87. {
  88. dmi_check_system(acpisleep_dmi_table);
  89. return 0;
  90. }
  91. core_initcall(acpisleep_dmi_init);