|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.1 (the "License"). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this file. ! 13: * ! 14: * The Original Code and all software distributed under the License are ! 15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 19: * License for the specific language governing rights and limitations ! 20: * under the License. ! 21: * ! 22: * @APPLE_LICENSE_HEADER_END@ ! 23: */ ! 24: ! 25: /* ! 26: * Copyright 1994 NeXT Computer, Inc. ! 27: * All rights reserved. ! 28: */ ! 29: ! 30: /* ! 31: * Power Management (PM) kernel interface. ! 32: * This implementation uses the Microsoft/Intel APM 1.1 interface. ! 33: */ ! 34: ! 35: #import <bsd/sys/time.h> ! 36: ! 37: #import <kern/power.h> ! 38: ! 39: #import <mach/mach_types.h> ! 40: ! 41: #import <machdep/i386/pmap.h> ! 42: #import <machdep/i386/seg.h> ! 43: #import <machdep/i386/table_inline.h> ! 44: #import <machdep/i386/desc_inline.h> ! 45: #import <machdep/i386/kernBootStruct.h> ! 46: #import <machdep/i386/bios.h> ! 47: #import <machdep/i386/APM_BIOS.h> ! 48: ! 49: static boolean_t APM_BIOS_connected; ! 50: static struct { ! 51: unsigned major; ! 52: unsigned minor; ! 53: } APM_BIOS_version; ! 54: ! 55: #define VERSION_EQ(maj,min) ((APM_BIOS_version.major == (maj)) && \ ! 56: (APM_BIOS_version.minor == (min))) ! 57: #define VERSION_GE(maj,min) ((APM_BIOS_version.major > (maj)) || \ ! 58: ((APM_BIOS_version.major == (maj)) && \ ! 59: (APM_BIOS_version.minor >= (min)))) ! 60: /* ! 61: * Note: we assume that the power management version is 1.0, ! 62: * because some machine report a bogus version. ! 63: * If we do the standard 1.0 "APM Connect" BIOS call in the booter, ! 64: * then the BIOS should give us APM 1.0 behavior. ! 65: */ ! 66: ! 67: static void ! 68: setUpGdtEntries() ! 69: { ! 70: KERNBOOTSTRUCT *kbp = KERNSTRUCT_ADDR; ! 71: ! 72: map_code((data_desc_t *) sel_to_gdt_entry(APMCODE32_SEL), ! 73: (vm_offset_t) KERNEL_LINEAR_BASE + kbp->apm_config.cs32_base, ! 74: (vm_size_t) kbp->apm_config.cs_length, ! 75: KERN_PRIV, ! 76: FALSE ! 77: ); ! 78: ! 79: map_code_16((data_desc_t *) sel_to_gdt_entry(APMCODE16_SEL), ! 80: (vm_offset_t) KERNEL_LINEAR_BASE + kbp->apm_config.cs16_base, ! 81: (vm_size_t) kbp->apm_config.cs_length, ! 82: KERN_PRIV, ! 83: FALSE ! 84: ); ! 85: ! 86: map_data((data_desc_t *) sel_to_gdt_entry(APMDATA_SEL), ! 87: (vm_offset_t) KERNEL_LINEAR_BASE + kbp->apm_config.ds_base, ! 88: (vm_size_t) kbp->apm_config.ds_length, ! 89: KERN_PRIV, ! 90: FALSE ! 91: ); ! 92: ! 93: APM_BIOS_addr = kbp->apm_config.entry_offset; ! 94: } ! 95: ! 96: /* ! 97: * Initialize PM support. Returns TRUE if PM is available. ! 98: */ ! 99: PMReturn PMConnect(void) ! 100: { ! 101: KERNBOOTSTRUCT *kbp = KERNSTRUCT_ADDR; ! 102: ! 103: APM_BIOS_version.major = kbp->apm_config.major_vers; ! 104: APM_BIOS_version.minor = kbp->apm_config.minor_vers; ! 105: ! 106: if (kbp->apm_config.connected) { ! 107: APM_BIOS_connected = TRUE; ! 108: setUpGdtEntries(); ! 109: printf("Power management is enabled.\n"); ! 110: return PM_R_SUCCESS; ! 111: } ! 112: return PM_R_NO_PM; ! 113: } ! 114: ! 115: /* ! 116: * Return PM control to previous user (probably the BIOS). ! 117: */ ! 118: PMReturn PMDisconnect(void) ! 119: { ! 120: return PM_R_SUCCESS; ! 121: } ! 122: ! 123: /* ! 124: * Inform PM of the CPU state. If the CPU is idle, PM may ! 125: * put the CPU in a power-saving state until the next system event ! 126: * (typically an interrupt). Marking the CPU busy will ensure ! 127: * that the CPU is running at full speed. ! 128: */ ! 129: PMReturn PMSetCpuState( ! 130: PMCpuState state ! 131: ) ! 132: { ! 133: boolean_t ret; ! 134: ! 135: if (APM_BIOS_connected) { ! 136: switch (state) { ! 137: case PM_CPU_IDLE: ! 138: ret = APMBIOS_Idle(); ! 139: break; ! 140: case PM_CPU_BUSY: ! 141: ret = APMBIOS_Busy(); ! 142: break; ! 143: default: ! 144: ret = FALSE; ! 145: } ! 146: if (ret == FALSE) ! 147: return PM_R_BAD_STATE; ! 148: } else { ! 149: if (state == PM_CPU_IDLE) { ! 150: asm volatile("hlt"); ! 151: } ! 152: } ! 153: return PM_R_SUCCESS; ! 154: } ! 155: ! 156: /* ! 157: * Set the power state of a device or the entire computer. ! 158: */ ! 159: PMReturn PMSetPowerState( ! 160: PMDeviceID device, ! 161: PMPowerState state ! 162: ) ! 163: { ! 164: union { ! 165: struct { ! 166: unsigned int deviceNumber :8; ! 167: unsigned int deviceType :8; ! 168: } device; ! 169: unsigned short data; ! 170: } du; ! 171: union { ! 172: PMPowerState state; ! 173: unsigned short data; ! 174: } su; ! 175: PMReturn ret; ! 176: ! 177: /* Eventually this should differentiate between devices. */ ! 178: if (device.deviceType == PM_SYSTEM && device.deviceNumber == 1) { ! 179: _io_setDriverPowerState(state); ! 180: } ! 181: ! 182: if (APM_BIOS_connected) { ! 183: if (device.deviceType == PM_SYSTEM && device.deviceNumber == 1) { ! 184: /* ! 185: * In PM 1.1 and 1.0, ! 186: * you can't set the system state to "ready". ! 187: */ ! 188: if (state == PM_READY) ! 189: return PM_R_BAD_STATE; ! 190: /* ! 191: * In PM 1.0, you can't set the system state to "off". ! 192: */ ! 193: if (state == PM_OFF) ! 194: return PM_R_BAD_STATE; ! 195: } ! 196: du.device.deviceNumber = device.deviceNumber; ! 197: du.device.deviceType = device.deviceType; ! 198: su.state = state; ! 199: return APMBIOS_SetPowerState(du.data, su.data); ! 200: } ! 201: return PM_R_NOT_CONNECTED; ! 202: } ! 203: ! 204: /* ! 205: * Get a power event from PM, if one has occurred. ! 206: */ ! 207: PMReturn PMGetPowerEvent( ! 208: PMPowerEvent *event ! 209: ) ! 210: { ! 211: unsigned short event_code; ! 212: PMReturn ret; ! 213: ! 214: if (APM_BIOS_connected) { ! 215: if ((ret = APMBIOS_GetPowerEvent(&event_code)) == PM_R_SUCCESS) { ! 216: *event = (PMPowerEvent)event_code; ! 217: return PM_R_SUCCESS; ! 218: } ! 219: return ret; ! 220: } ! 221: return PM_R_NOT_CONNECTED; ! 222: } ! 223: ! 224: /* ! 225: * Get the power state of the computer. ! 226: */ ! 227: PMReturn PMGetPowerStatus( ! 228: PMPowerStatus *status ! 229: ) ! 230: { ! 231: unsigned char line_status, batt_status, batt_life; ! 232: PMReturn ret; ! 233: ! 234: if (APM_BIOS_connected) { ! 235: if ((ret = APMBIOS_GetPowerStatus(&line_status, &batt_status, ! 236: &batt_life)) == PM_R_SUCCESS) { ! 237: status->lineStatus = (PMLineStatus)line_status; ! 238: status->batteryStatus = (PMBatteryStatus)batt_status; ! 239: status->batteryLife = (batt_life == 0xFF) ? -1 : (int)batt_life; ! 240: return PM_R_SUCCESS; ! 241: } else { ! 242: return ret; ! 243: } ! 244: } ! 245: return PM_R_NOT_CONNECTED; ! 246: } ! 247: ! 248: /* ! 249: * Enable or disable power management by the computer. ! 250: * If enable == PM_ENABLED, the computer can take power saving steps ! 251: * when the CPU state is idle. If enable == PM_DISABLED, no automatic ! 252: * power saving steps will be taken and power management functions ! 253: * will be disabled. ! 254: */ ! 255: PMReturn PMSetPowerManagement( ! 256: PMDeviceID device, ! 257: PMPowerManagementState state ! 258: ) ! 259: { ! 260: if (APM_BIOS_connected) { ! 261: if (device.deviceType == PM_SYSTEM && device.deviceNumber == 1) ! 262: return APMBIOS_SetSystemPowerManagement(state); ! 263: else ! 264: return PM_R_BAD_ID; ! 265: } ! 266: ! 267: return PM_R_NOT_CONNECTED; ! 268: } ! 269: ! 270: /* ! 271: * Restores the default settings for all power management settings. ! 272: */ ! 273: PMReturn PMRestoreDefaults(void) ! 274: { ! 275: if (APM_BIOS_connected) ! 276: return APMBIOS_RestoreDefaults(); ! 277: else ! 278: return PM_R_NOT_CONNECTED; ! 279: } ! 280: ! 281: /* ! 282: * Update current kernel clock from real-time clock. ! 283: */ ! 284: void PMUpdateClock(void) ! 285: { ! 286: /* THIS IS WRONG!! ! 287: extern struct timeval time; ! 288: readtodc(&time.tv_sec); ! 289: */ ! 290: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.