windows-nt/Source/XPSP1/NT/base/boot/detect/i386/hwapm.c
2020-09-26 16:20:57 +08:00

227 lines
4.9 KiB
C

/*++
Copyright (c) 1990, 1991 Microsoft Corporation
Module Name:
hwapm.c
Abstract:
Author:
Environment:
Real mode.
Revision History:
--*/
#include "hwdetect.h"
#include <string.h>
#include "apm.h"
#include <ntapmsdk.h>
ULONG
HwWriteLog(
PUCHAR p,
UCHAR loc,
ULONG data
);
UCHAR DetName[] = "DETLOG1";
VOID Int15 (PULONG, PULONG, PULONG, PULONG, PULONG);
BOOLEAN
HwGetApmSystemData(
PVOID Buf
)
{
PAPM_REGISTRY_INFO ApmEntry;
ULONG RegEax, RegEbx, RegEcx, RegEdx, CyFlag;
UCHAR ApmMajor, ApmMinor;
PUCHAR lp, p;
ApmEntry = Buf;
ApmEntry->Signature[0] = 'A';
ApmEntry->Signature[1] = 'P';
ApmEntry->Signature[2] = 'M';
ApmEntry->Valid = 0;
lp = &(ApmEntry->DetectLog[0]);
p = DetName;
while (*p != '\0') {
*lp = *p;
p++;
lp++;
}
//
// Perform APM installation check
//
RegEax = APM_INSTALLATION_CHECK;
RegEbx = APM_DEVICE_BIOS;
Int15 (&RegEax, &RegEbx, &RegEcx, &RegEdx, &CyFlag);
if (CyFlag ||
(RegEbx & 0xff) != 'M' ||
((RegEbx >> 8) & 0xff) != 'P') {
//
// this is a case where int15 says apm just isn't there,
// so tell the caller to not even create the node
//
return FALSE;
}
//
// If we get here, we have an APM bios. If we just call it,
// we may get grief. So we will connect in real mode, then
// set our version to whatever the driver says it is, or 1.2,
// whichever is LESS. Then query options again.
//
ApmMajor = (UCHAR) (RegEax >> 8) & 0xff;
ApmMinor = (UCHAR) RegEax & 0xff;
if (ApmMajor > 1) ApmMajor = 1;
if (ApmMinor > 2) ApmMinor = 2;
//
// Connect to Real mode interface
//
RegEax = APM_REAL_MODE_CONNECT;
RegEbx = APM_DEVICE_BIOS;
Int15 (&RegEax, &RegEbx, &RegEcx, &RegEdx, &CyFlag);
if (CyFlag) {
lp += HwWriteLog(lp, 'A', RegEax);
return TRUE;
}
//
// Call APM Driver Version in real mode, and set the driver
// version to be MIN(v1.2, apm version of the machine)
//
RegEax = APM_DRIVER_VERSION;
RegEbx = APM_DEVICE_BIOS;
RegEcx = ((ApmMajor << 8) | ApmMinor) & 0xffff;
Int15 (&RegEax, &RegEbx, &RegEcx, &RegEdx, &CyFlag);
if (CyFlag) {
lp += HwWriteLog(lp, 'B', RegEax);
return TRUE;
}
//
// Perform APM installation check again
//
RegEax = APM_INSTALLATION_CHECK;
RegEbx = APM_DEVICE_BIOS;
Int15 (&RegEax, &RegEbx, &RegEcx, &RegEdx, &CyFlag);
if (CyFlag) {
lp += HwWriteLog(lp, 'C', RegEax);
return TRUE;
}
ApmEntry->ApmRevMajor = (UCHAR) (RegEax >> 8) & 0xff;
ApmEntry->ApmRevMinor = (UCHAR) RegEax & 0xff;
ApmEntry->ApmInstallFlags = (USHORT) RegEcx;
//
// Disconnect from real mode interface
//
RegEax = APM_DISCONNECT;
RegEbx = APM_DEVICE_BIOS;
Int15 (&RegEax, &RegEbx, &RegEcx, &RegEdx, &CyFlag);
if (CyFlag) {
lp += HwWriteLog(lp, 'D', RegEax);
return TRUE;
}
//
// If we get this far, there's an APM bios in the machine,
// and we've told it that we're the latest version we think
// it and we like, so now, in theory, things should just work....
//
if (ApmEntry->ApmInstallFlags & APM_MODE_16BIT) {
//
// Connect to 16 bit interface
//
RegEax = APM_PROTECT_MODE_16bit_CONNECT;
RegEbx = APM_DEVICE_BIOS;
Int15 (&RegEax, &RegEbx, &RegEcx, &RegEdx, &CyFlag);
if (CyFlag) {
lp += HwWriteLog(lp, 'E', RegEax);
return TRUE;
}
ApmEntry->Code16BitSegment = (USHORT) RegEax;
ApmEntry->Code16BitOffset = (USHORT) RegEbx;
ApmEntry->Data16BitSegment = (USHORT) RegEcx;
//
// On most bioses, the following call just works.
// On some, it doesn't, and their authors point at the spec.
// And finally, most bioses don't seem to need this call
// in the first place.
// We cannot do it in ntapm.sys because it's on the loader's
// hibernate resume path as well as here.
//
// SO> make the call, report any error, but IGNORE it.
//
RegEax = APM_DRIVER_VERSION;
RegEbx = APM_DEVICE_BIOS;
RegEcx = ((ApmMajor << 8) | ApmMinor) & 0xffff;
Int15 (&RegEax, &RegEbx, &RegEcx, &RegEdx, &CyFlag);
if (CyFlag) {
lp += HwWriteLog(lp, 'F', RegEax);
ApmEntry->Valid = 1; // pretend it worked....
return TRUE;
}
ApmEntry->Valid = 1;
return TRUE;
}
HwWriteLog(lp, 'H', ApmEntry->ApmInstallFlags);
return TRUE;
}
ULONG
HwWriteLog(
PUCHAR p,
UCHAR loc,
ULONG data
)
{
p[0] = loc;
p[1] = (UCHAR)(data & 0xff);
p[2] = (UCHAR)((data & 0xff00) >> 8);
return 4;
}