1 /* 2 * acpi_system.c - ACPI System Driver ($Revision: 57 $) 3 * 4 * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> 5 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> 6 * 7 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation; either version 2 of the License, or (at 12 * your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, but 15 * WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 * General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License along 20 * with this program; if not, write to the Free Software Foundation, Inc., 21 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 22 * 23 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 24 */ 25 26 /* Modified for ReactOS and latest ACPICA 27 * Copyright (C)2009 Samuel Serapion 28 */ 29 30 #include <precomp.h> 31 32 #define NDEBUG 33 #include <debug.h> 34 35 ACPI_STATUS acpi_system_save_state(UINT32); 36 37 #define _COMPONENT ACPI_SYSTEM_COMPONENT 38 ACPI_MODULE_NAME ("acpi_system") 39 40 #define PREFIX "ACPI: " 41 42 static int acpi_system_add (struct acpi_device *device); 43 static int acpi_system_remove (struct acpi_device *device, int type); 44 45 ACPI_STATUS acpi_suspend (UINT32 state); 46 47 static struct acpi_driver acpi_system_driver = { 48 {0,0}, 49 ACPI_SYSTEM_DRIVER_NAME, 50 ACPI_SYSTEM_CLASS, 51 0, 52 0, 53 ACPI_SYSTEM_HID, 54 {acpi_system_add, acpi_system_remove} 55 }; 56 57 struct acpi_system 58 { 59 ACPI_HANDLE handle; 60 UINT8 states[ACPI_S_STATE_COUNT]; 61 }; 62 63 64 static int 65 acpi_system_add ( 66 struct acpi_device *device) 67 { 68 ACPI_STATUS status = AE_OK; 69 struct acpi_system *system = NULL; 70 UINT8 i = 0; 71 72 ACPI_FUNCTION_TRACE("acpi_system_add"); 73 74 if (!device) 75 return_VALUE(-1); 76 77 system = ExAllocatePoolWithTag(NonPagedPool,sizeof(struct acpi_system),'IPCA'); 78 if (!system) 79 return_VALUE(-14); 80 memset(system, 0, sizeof(struct acpi_system)); 81 82 system->handle = device->handle; 83 sprintf(acpi_device_name(device), "%s", ACPI_SYSTEM_DEVICE_NAME); 84 sprintf(acpi_device_class(device), "%s", ACPI_SYSTEM_CLASS); 85 acpi_driver_data(device) = system; 86 87 DPRINT("%s [%s] (supports", 88 acpi_device_name(device), acpi_device_bid(device)); 89 for (i=0; i<ACPI_S_STATE_COUNT; i++) { 90 UINT8 type_a, type_b; 91 status = AcpiGetSleepTypeData(i, &type_a, &type_b); 92 switch (i) { 93 case ACPI_STATE_S4: 94 if (/*AcpiGbl_FACS->S4bios_f &&*/ 95 0 != AcpiGbl_FADT.SmiCommand) { 96 DPRINT(" S4bios\n"); 97 system->states[i] = 1; 98 } 99 /* no break */ 100 default: 101 if (ACPI_SUCCESS(status)) { 102 system->states[i] = 1; 103 DPRINT(" S%d", i); 104 } 105 } 106 } 107 108 //#ifdef CONFIG_PM 109 // /* Install the soft-off (S5) handler. */ 110 // if (system->states[ACPI_STATE_S5]) { 111 // pm_power_off = acpi_power_off; 112 // register_sysrq_key('o', &sysrq_acpi_poweroff_op); 113 // } 114 //#endif 115 116 return_VALUE(0); 117 } 118 119 static int 120 acpi_system_remove ( 121 struct acpi_device *device, 122 int type) 123 { 124 struct acpi_system *system = NULL; 125 126 ACPI_FUNCTION_TRACE("acpi_system_remove"); 127 128 if (!device || !acpi_driver_data(device)) 129 return_VALUE(-1); 130 131 system = (struct acpi_system *) acpi_driver_data(device); 132 133 //#ifdef CONFIG_PM 134 // /* Remove the soft-off (S5) handler. */ 135 // if (system->states[ACPI_STATE_S5]) { 136 // unregister_sysrq_key('o', &sysrq_acpi_poweroff_op); 137 // pm_power_off = NULL; 138 // } 139 //#endif 140 // 141 // 142 ExFreePoolWithTag(system, 'IPCA'); 143 144 return 0; 145 } 146 147 /** 148 * acpi_system_restore_state - OS-specific restoration of state 149 * @state: sleep state we're exiting 150 * 151 * Note that if we're coming back from S4, the memory image should have 152 * already been loaded from the disk and is already in place. (Otherwise how 153 * else would we be here?). 154 */ 155 ACPI_STATUS 156 acpi_system_restore_state( 157 UINT32 state) 158 { 159 /* 160 * We should only be here if we're coming back from STR or STD. 161 * And, in the case of the latter, the memory image should have already 162 * been loaded from disk. 163 */ 164 if (state > ACPI_STATE_S1) { 165 //acpi_restore_state_mem(); 166 167 /* Do _early_ resume for irqs. Required by 168 * ACPI specs. 169 */ 170 /* TBD: call arch dependant reinitialization of the 171 * interrupts. 172 */ 173 #ifdef _X86_ 174 //init_8259A(0); 175 #endif 176 /* wait for power to come back */ 177 KeStallExecutionProcessor(100); 178 179 } 180 181 /* Be really sure that irqs are disabled. */ 182 //ACPI_DISABLE_IRQS(); 183 184 /* Wait a little again, just in case... */ 185 KeStallExecutionProcessor(10); 186 187 /* enable interrupts once again */ 188 //ACPI_ENABLE_IRQS(); 189 190 /* turn all the devices back on */ 191 //if (state > ACPI_STATE_S1) 192 //pm_send_all(PM_RESUME, (void *)0); 193 194 return AE_OK; 195 } 196 197 198 /** 199 * acpi_system_save_state - save OS specific state and power down devices 200 * @state: sleep state we're entering. 201 * 202 * This handles saving all context to memory, and possibly disk. 203 * First, we call to the device driver layer to save device state. 204 * Once we have that, we save whatevery processor and kernel state we 205 * need to memory. 206 * If we're entering S4, we then write the memory image to disk. 207 * 208 * Only then it is safe for us to power down devices, since we may need 209 * the disks and upstream buses to write to. 210 */ 211 ACPI_STATUS 212 acpi_system_save_state( 213 UINT32 state) 214 { 215 int error = 0; 216 217 /* Send notification to devices that they will be suspended. 218 * If any device or driver cannot make the transition, either up 219 * or down, we'll get an error back. 220 */ 221 /*if (state > ACPI_STATE_S1) { 222 error = pm_send_all(PM_SAVE_STATE, (void *)3); 223 if (error) 224 return AE_ERROR; 225 }*/ 226 227 //if (state <= ACPI_STATE_S5) { 228 // /* Tell devices to stop I/O and actually save their state. 229 // * It is theoretically possible that something could fail, 230 // * so handle that gracefully.. 231 // */ 232 // if (state > ACPI_STATE_S1 && state != ACPI_STATE_S5) { 233 // error = pm_send_all(PM_SUSPEND, (void *)3); 234 // if (error) { 235 // /* Tell devices to restore state if they have 236 // * it saved and to start taking I/O requests. 237 // */ 238 // pm_send_all(PM_RESUME, (void *)0); 239 // return error; 240 // } 241 // } 242 243 /* flush caches */ 244 ACPI_FLUSH_CPU_CACHE(); 245 246 /* Do arch specific saving of state. */ 247 if (state > ACPI_STATE_S1) { 248 error = 0;//acpi_save_state_mem(); 249 250 /* TBD: if no s4bios, write codes for 251 * acpi_save_state_disk()... 252 */ 253 #if 0 254 if (!error && (state == ACPI_STATE_S4)) 255 error = acpi_save_state_disk(); 256 #endif 257 /*if (error) { 258 pm_send_all(PM_RESUME, (void *)0); 259 return error; 260 }*/ 261 } 262 //} 263 /* disable interrupts 264 * Note that acpi_suspend -- our caller -- will do this once we return. 265 * But, we want it done early, so we don't get any surprises during 266 * the device suspend sequence. 267 */ 268 //ACPI_DISABLE_IRQS(); 269 270 /* Unconditionally turn off devices. 271 * Obvious if we enter a sleep state. 272 * If entering S5 (soft off), this should put devices in a 273 * quiescent state. 274 */ 275 276 //if (state > ACPI_STATE_S1) { 277 // error = pm_send_all(PM_SUSPEND, (void *)3); 278 279 // /* We're pretty screwed if we got an error from this. 280 // * We try to recover by simply calling our own restore_state 281 // * function; see above for definition. 282 // * 283 // * If it's S5 though, go through with it anyway.. 284 // */ 285 // if (error && state != ACPI_STATE_S5) 286 // acpi_system_restore_state(state); 287 //} 288 return error ? AE_ERROR : AE_OK; 289 } 290 291 292 /**************************************************************************** 293 * 294 * FUNCTION: acpi_system_suspend 295 * 296 * PARAMETERS: %state: Sleep state to enter. 297 * 298 * RETURN: ACPI_STATUS, whether or not we successfully entered and 299 * exited sleep. 300 * 301 * DESCRIPTION: Perform OS-specific action to enter sleep state. 302 * This is the final step in going to sleep, per spec. If we 303 * know we're coming back (i.e. not entering S5), we save the 304 * processor flags. [ We'll have to save and restore them anyway, 305 * so we use the arch-agnostic save_flags and restore_flags 306 * here.] We then set the place to return to in arch-specific 307 * globals using arch_set_return_point. Finally, we call the 308 * ACPI function to write the proper values to I/O ports. 309 * 310 ****************************************************************************/ 311 312 ACPI_STATUS 313 acpi_system_suspend( 314 UINT32 state) 315 { 316 ACPI_STATUS status = AE_ERROR; 317 //unsigned long flags = 0; 318 319 //local_irq_save(flags); 320 /* kernel_fpu_begin(); */ 321 322 switch (state) { 323 case ACPI_STATE_S1: 324 case ACPI_STATE_S5: 325 //barrier(); 326 status = AcpiEnterSleepState(state); 327 break; 328 case ACPI_STATE_S4: 329 //do_suspend_lowlevel_s4bios(0); 330 break; 331 } 332 333 /* kernel_fpu_end(); */ 334 //local_irq_restore(flags); 335 336 return status; 337 } 338 339 340 341 /** 342 * acpi_suspend - OS-agnostic system suspend/resume support (S? states) 343 * @state: state we're entering 344 * 345 */ 346 ACPI_STATUS 347 acpi_suspend ( 348 UINT32 state) 349 { 350 ACPI_STATUS status; 351 352 /* only support S1 and S5 on kernel 2.4 */ 353 //if (state != ACPI_STATE_S1 && state != ACPI_STATE_S4 354 // && state != ACPI_STATE_S5) 355 // return AE_ERROR; 356 357 358 //if (ACPI_STATE_S4 == state) { 359 // /* For s4bios, we need a wakeup address. */ 360 // if (1 == AcpiGbl_FACS->S4bios_f && 361 // 0 != AcpiGbl_FADT->smi_cmd) { 362 // if (!acpi_wakeup_address) 363 // return AE_ERROR; 364 // AcpiSetFirmwareWakingVector((acpi_physical_address) acpi_wakeup_address); 365 // } else 366 // /* We don't support S4 under 2.4. Give up */ 367 // return AE_ERROR; 368 //} 369 AcpiEnterSleepStatePrep(state); 370 371 status = AcpiEnterSleepState(state); 372 if (!ACPI_SUCCESS(status) && state != ACPI_STATE_S5) 373 return status; 374 375 /* disable interrupts and flush caches */ 376 _disable(); 377 ACPI_FLUSH_CPU_CACHE(); 378 379 /* perform OS-specific sleep actions */ 380 status = acpi_system_suspend(state); 381 382 /* Even if we failed to go to sleep, all of the devices are in an suspended 383 * mode. So, we run these unconditionally to make sure we have a usable system 384 * no matter what. 385 */ 386 AcpiLeaveSleepState(state); 387 acpi_system_restore_state(state); 388 389 /* make sure interrupts are enabled */ 390 _enable(); 391 392 /* reset firmware waking vector */ 393 AcpiSetFirmwareWakingVector(0, 0); 394 395 return status; 396 } 397 398 int 399 acpi_system_init (void) 400 { 401 int result = 0; 402 403 ACPI_FUNCTION_TRACE("acpi_system_init"); 404 405 result = acpi_bus_register_driver(&acpi_system_driver); 406 if (result < 0) 407 return_VALUE(AE_NOT_FOUND); 408 409 return_VALUE(0); 410 } 411 412 413 void 414 acpi_system_exit (void) 415 { 416 ACPI_FUNCTION_TRACE("acpi_system_exit"); 417 acpi_bus_unregister_driver(&acpi_system_driver); 418 return_VOID; 419 } 420 421