apm.c revision da50fc9dde218b85a902c22963ce24215a067801
/* $Id$ */
/** @file
* APM BIOS support. Implements APM version 1.2.
*/
/*
* Copyright (C) 2004-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
#include <stdint.h>
#include <string.h>
#include "biosint.h"
#include "inlines.h"
#if DEBUG_APM
#else
# define BX_DEBUG_APM(...)
#endif
/* Implemented in assembly. */
extern void apm_pm16_entry(void);
extern void apm_pm32_entry(void);
/* APM function codes. */
enum apm_func {
};
enum apm_error {
};
enum apm_power_state {
};
// @todo: merge with system.c
/* The APM BIOS interface uses 32-bit registers *only* in the 32-bit
* registers all the time, simply set the high words of those registers
* when necessary.
*/
#pragma aux set_ebx_hi = \
".386" \
"shl ebx, 16" \
#pragma aux set_esi_hi = \
".386" \
"shl esi, 16" \
/* The APM handler has unique requirements. It must be callable from real and
* protected mode, both 16-bit and 32-bit. In protected mode, the caller must
* ensures that appropriate selectors are available; these only cover the BIOS
* code and data, hence the BIOS Data Area or EBDA cannot be accessed. CMOS is
* a good place to store information which needs to be accessible from several
* different contexts.
*
* Note that the 32-bit protected-mode handler only needs to thunk down to the
* 16-bit code. There's no need for separate 16-bit and 32-bit implementation.
*/
/* Output a null-terminated string to a specified port, without the
* terminating null character.
*/
#pragma aux apm_out_str_asm = \
"mov al, [bx]" \
"next:" \
"out dx, al" \
"inc bx" \
"mov al, [bx]" \
"or al, al" \
"jnz next" \
/* Wrapper to avoid unnecessary inlining. */
{
if (*s)
apm_out_str_asm(port, s);
}
{
CLEAR_CF(); /* Boldly expect success. */
switch (GET_AL()) {
case APM_CHECK:
break;
case APM_RM_CONN:
// @todo: validate device ID
// @todo: validate current connection state
// @todo: change connection state
break;
case APM_PM_CONN:
// @todo: validate device ID
// @todo: validate current connection state
// @todo: change connection state
break;
case APM_32_CONN:
// @todo: validate device ID
// @todo: validate current connection state
// @todo: change connection state
set_ebx_hi(0);
break;
case APM_IDLE:
int_enable(); /* Simply halt the CPU with interrupts enabled. */
halt();
break;
case APM_SET_PWR:
// @todo: validate device ID
// @todo: validate current connection state
switch (CX) {
case APM_PS_STANDBY:
break;
case APM_PS_SUSPEND:
break;
case APM_PS_OFF:
break;
default:
SET_CF();
}
break;
case APM_DRV_VER:
break;
case APM_DISCONN:
// @todo: actually perform a disconnect...
case APM_BUSY: /* Nothing to do as APM Idle doesn't slow CPU clock. */
break;
case APM_GET_EVT:
// @todo: error should be different if interface not connected + engaged
SET_CF();
break;
default:
SET_CF();
}
}