Annotation of kernel/machdep/i386/APM_i386.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.