Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygensystem.c
Go to the documentation of this file.
00001 /* 00002 * acpi_system.c - ACPI System Driver ($Revision: 57 $) 00003 * 00004 * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> 00005 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> 00006 * 00007 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 00008 * 00009 * This program is free software; you can redistribute it and/or modify 00010 * it under the terms of the GNU General Public License as published by 00011 * the Free Software Foundation; either version 2 of the License, or (at 00012 * your option) any later version. 00013 * 00014 * This program is distributed in the hope that it will be useful, but 00015 * WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00017 * General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU General Public License along 00020 * with this program; if not, write to the Free Software Foundation, Inc., 00021 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 00022 * 00023 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 00024 */ 00025 00026 /* Modified for ReactOS and latest ACPICA 00027 * Copyright (C)2009 Samuel Serapion 00028 */ 00029 #include <ntddk.h> 00030 #include <acpi.h> 00031 #include <acpi_bus.h> 00032 #include <acpi_drivers.h> 00033 #include "list.h" 00034 00035 #define NDEBUG 00036 #include <debug.h> 00037 00038 ACPI_STATUS acpi_system_save_state(UINT32); 00039 00040 #define _COMPONENT ACPI_SYSTEM_COMPONENT 00041 ACPI_MODULE_NAME ("acpi_system") 00042 00043 #define PREFIX "ACPI: " 00044 00045 static int acpi_system_add (struct acpi_device *device); 00046 static int acpi_system_remove (struct acpi_device *device, int type); 00047 00048 ACPI_STATUS acpi_suspend (UINT32 state); 00049 00050 static struct acpi_driver acpi_system_driver = { 00051 {0,0}, 00052 ACPI_SYSTEM_DRIVER_NAME, 00053 ACPI_SYSTEM_CLASS, 00054 0, 00055 0, 00056 ACPI_SYSTEM_HID, 00057 {acpi_system_add, acpi_system_remove} 00058 }; 00059 00060 struct acpi_system 00061 { 00062 ACPI_HANDLE handle; 00063 UINT8 states[ACPI_S_STATE_COUNT]; 00064 }; 00065 00066 00067 static int 00068 acpi_system_add ( 00069 struct acpi_device *device) 00070 { 00071 int result = 0; 00072 ACPI_STATUS status = AE_OK; 00073 struct acpi_system *system = NULL; 00074 UINT8 i = 0; 00075 00076 ACPI_FUNCTION_TRACE("acpi_system_add"); 00077 00078 if (!device) 00079 return_VALUE(-1); 00080 00081 system = ExAllocatePoolWithTag(NonPagedPool,sizeof(struct acpi_system),'IPCA'); 00082 if (!system) 00083 return_VALUE(-14); 00084 memset(system, 0, sizeof(struct acpi_system)); 00085 00086 system->handle = device->handle; 00087 sprintf(acpi_device_name(device), "%s", ACPI_SYSTEM_DEVICE_NAME); 00088 sprintf(acpi_device_class(device), "%s", ACPI_SYSTEM_CLASS); 00089 acpi_driver_data(device) = system; 00090 00091 DPRINT("%s [%s] (supports", 00092 acpi_device_name(device), acpi_device_bid(device)); 00093 for (i=0; i<ACPI_S_STATE_COUNT; i++) { 00094 UINT8 type_a, type_b; 00095 status = AcpiGetSleepTypeData(i, &type_a, &type_b); 00096 switch (i) { 00097 case ACPI_STATE_S4: 00098 if (/*AcpiGbl_FACS->S4bios_f &&*/ 00099 0 != AcpiGbl_FADT.SmiCommand) { 00100 DPRINT(" S4bios"); 00101 system->states[i] = 1; 00102 } 00103 /* no break */ 00104 default: 00105 if (ACPI_SUCCESS(status)) { 00106 system->states[i] = 1; 00107 DPRINT(" S%d", i); 00108 } 00109 } 00110 } 00111 00112 //#ifdef CONFIG_PM 00113 // /* Install the soft-off (S5) handler. */ 00114 // if (system->states[ACPI_STATE_S5]) { 00115 // pm_power_off = acpi_power_off; 00116 // register_sysrq_key('o', &sysrq_acpi_poweroff_op); 00117 // } 00118 //#endif 00119 00120 if (result) 00121 ExFreePoolWithTag(system, 'IPCA'); 00122 00123 return_VALUE(result); 00124 } 00125 00126 static int 00127 acpi_system_remove ( 00128 struct acpi_device *device, 00129 int type) 00130 { 00131 struct acpi_system *system = NULL; 00132 00133 ACPI_FUNCTION_TRACE("acpi_system_remove"); 00134 00135 if (!device || !acpi_driver_data(device)) 00136 return_VALUE(-1); 00137 00138 system = (struct acpi_system *) acpi_driver_data(device); 00139 00140 //#ifdef CONFIG_PM 00141 // /* Remove the soft-off (S5) handler. */ 00142 // if (system->states[ACPI_STATE_S5]) { 00143 // unregister_sysrq_key('o', &sysrq_acpi_poweroff_op); 00144 // pm_power_off = NULL; 00145 // } 00146 //#endif 00147 // 00148 // 00149 ExFreePoolWithTag(system, 'IPCA'); 00150 00151 return 0; 00152 } 00153 00162 ACPI_STATUS 00163 acpi_system_restore_state( 00164 UINT32 state) 00165 { 00166 /* 00167 * We should only be here if we're coming back from STR or STD. 00168 * And, in the case of the latter, the memory image should have already 00169 * been loaded from disk. 00170 */ 00171 if (state > ACPI_STATE_S1) { 00172 //acpi_restore_state_mem(); 00173 00174 /* Do _early_ resume for irqs. Required by 00175 * ACPI specs. 00176 */ 00177 /* TBD: call arch dependant reinitialization of the 00178 * interrupts. 00179 */ 00180 #ifdef _X86_ 00181 //init_8259A(0); 00182 #endif 00183 /* wait for power to come back */ 00184 KeStallExecutionProcessor(100); 00185 00186 } 00187 00188 /* Be really sure that irqs are disabled. */ 00189 //ACPI_DISABLE_IRQS(); 00190 00191 /* Wait a little again, just in case... */ 00192 KeStallExecutionProcessor(10); 00193 00194 /* enable interrupts once again */ 00195 //ACPI_ENABLE_IRQS(); 00196 00197 /* turn all the devices back on */ 00198 //if (state > ACPI_STATE_S1) 00199 //pm_send_all(PM_RESUME, (void *)0); 00200 00201 return AE_OK; 00202 } 00203 00204 00218 ACPI_STATUS 00219 acpi_system_save_state( 00220 UINT32 state) 00221 { 00222 int error = 0; 00223 00224 /* Send notification to devices that they will be suspended. 00225 * If any device or driver cannot make the transition, either up 00226 * or down, we'll get an error back. 00227 */ 00228 /*if (state > ACPI_STATE_S1) { 00229 error = pm_send_all(PM_SAVE_STATE, (void *)3); 00230 if (error) 00231 return AE_ERROR; 00232 }*/ 00233 00234 //if (state <= ACPI_STATE_S5) { 00235 // /* Tell devices to stop I/O and actually save their state. 00236 // * It is theoretically possible that something could fail, 00237 // * so handle that gracefully.. 00238 // */ 00239 // if (state > ACPI_STATE_S1 && state != ACPI_STATE_S5) { 00240 // error = pm_send_all(PM_SUSPEND, (void *)3); 00241 // if (error) { 00242 // /* Tell devices to restore state if they have 00243 // * it saved and to start taking I/O requests. 00244 // */ 00245 // pm_send_all(PM_RESUME, (void *)0); 00246 // return error; 00247 // } 00248 // } 00249 00250 /* flush caches */ 00251 ACPI_FLUSH_CPU_CACHE(); 00252 00253 /* Do arch specific saving of state. */ 00254 if (state > ACPI_STATE_S1) { 00255 error = 0;//acpi_save_state_mem(); 00256 00257 /* TBD: if no s4bios, write codes for 00258 * acpi_save_state_disk()... 00259 */ 00260 #if 0 00261 if (!error && (state == ACPI_STATE_S4)) 00262 error = acpi_save_state_disk(); 00263 #endif 00264 /*if (error) { 00265 pm_send_all(PM_RESUME, (void *)0); 00266 return error; 00267 }*/ 00268 } 00269 //} 00270 /* disable interrupts 00271 * Note that acpi_suspend -- our caller -- will do this once we return. 00272 * But, we want it done early, so we don't get any suprises during 00273 * the device suspend sequence. 00274 */ 00275 //ACPI_DISABLE_IRQS(); 00276 00277 /* Unconditionally turn off devices. 00278 * Obvious if we enter a sleep state. 00279 * If entering S5 (soft off), this should put devices in a 00280 * quiescent state. 00281 */ 00282 00283 //if (state > ACPI_STATE_S1) { 00284 // error = pm_send_all(PM_SUSPEND, (void *)3); 00285 00286 // /* We're pretty screwed if we got an error from this. 00287 // * We try to recover by simply calling our own restore_state 00288 // * function; see above for definition. 00289 // * 00290 // * If it's S5 though, go through with it anyway.. 00291 // */ 00292 // if (error && state != ACPI_STATE_S5) 00293 // acpi_system_restore_state(state); 00294 //} 00295 return error ? AE_ERROR : AE_OK; 00296 } 00297 00298 00299 /**************************************************************************** 00300 * 00301 * FUNCTION: acpi_system_suspend 00302 * 00303 * PARAMETERS: %state: Sleep state to enter. 00304 * 00305 * RETURN: ACPI_STATUS, whether or not we successfully entered and 00306 * exited sleep. 00307 * 00308 * DESCRIPTION: Perform OS-specific action to enter sleep state. 00309 * This is the final step in going to sleep, per spec. If we 00310 * know we're coming back (i.e. not entering S5), we save the 00311 * processor flags. [ We'll have to save and restore them anyway, 00312 * so we use the arch-agnostic save_flags and restore_flags 00313 * here.] We then set the place to return to in arch-specific 00314 * globals using arch_set_return_point. Finally, we call the 00315 * ACPI function to write the proper values to I/O ports. 00316 * 00317 ****************************************************************************/ 00318 00319 ACPI_STATUS 00320 acpi_system_suspend( 00321 UINT32 state) 00322 { 00323 ACPI_STATUS status = AE_ERROR; 00324 //unsigned long flags = 0; 00325 00326 //local_irq_save(flags); 00327 /* kernel_fpu_begin(); */ 00328 00329 switch (state) { 00330 case ACPI_STATE_S1: 00331 case ACPI_STATE_S5: 00332 //barrier(); 00333 status = AcpiEnterSleepState(state); 00334 break; 00335 case ACPI_STATE_S4: 00336 //do_suspend_lowlevel_s4bios(0); 00337 break; 00338 } 00339 00340 /* kernel_fpu_end(); */ 00341 //local_irq_restore(flags); 00342 00343 return status; 00344 } 00345 00346 00347 00353 ACPI_STATUS 00354 acpi_suspend ( 00355 UINT32 state) 00356 { 00357 ACPI_STATUS status; 00358 00359 /* only support S1 and S5 on kernel 2.4 */ 00360 //if (state != ACPI_STATE_S1 && state != ACPI_STATE_S4 00361 // && state != ACPI_STATE_S5) 00362 // return AE_ERROR; 00363 00364 00365 //if (ACPI_STATE_S4 == state) { 00366 // /* For s4bios, we need a wakeup address. */ 00367 // if (1 == AcpiGbl_FACS->S4bios_f && 00368 // 0 != AcpiGbl_FADT->smi_cmd) { 00369 // if (!acpi_wakeup_address) 00370 // return AE_ERROR; 00371 // AcpiSetFirmwareWakingVector((acpi_physical_address) acpi_wakeup_address); 00372 // } else 00373 // /* We don't support S4 under 2.4. Give up */ 00374 // return AE_ERROR; 00375 //} 00376 AcpiEnterSleepStatePrep(state); 00377 00378 status = AcpiEnterSleepState(state); 00379 if (!ACPI_SUCCESS(status) && state != ACPI_STATE_S5) 00380 return status; 00381 00382 /* disable interrupts and flush caches */ 00383 _disable(); 00384 ACPI_FLUSH_CPU_CACHE(); 00385 00386 /* perform OS-specific sleep actions */ 00387 status = acpi_system_suspend(state); 00388 00389 /* Even if we failed to go to sleep, all of the devices are in an suspended 00390 * mode. So, we run these unconditionaly to make sure we have a usable system 00391 * no matter what. 00392 */ 00393 AcpiLeaveSleepState(state); 00394 acpi_system_restore_state(state); 00395 00396 /* make sure interrupts are enabled */ 00397 _enable(); 00398 00399 /* reset firmware waking vector */ 00400 AcpiSetFirmwareWakingVector((ACPI_PHYSICAL_ADDRESS) 0); 00401 00402 return status; 00403 } 00404 00405 int 00406 acpi_system_init (void) 00407 { 00408 int result = 0; 00409 00410 ACPI_FUNCTION_TRACE("acpi_system_init"); 00411 00412 result = acpi_bus_register_driver(&acpi_system_driver); 00413 if (result < 0) 00414 return_VALUE(AE_NOT_FOUND); 00415 00416 return_VALUE(0); 00417 } 00418 00419 00420 void 00421 acpi_system_exit (void) 00422 { 00423 ACPI_FUNCTION_TRACE("acpi_system_exit"); 00424 acpi_bus_unregister_driver(&acpi_system_driver); 00425 return_VOID; 00426 } 00427 Generated on Sun May 27 2012 04:16:35 for ReactOS by
1.7.6.1
|