|
|
/*++
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; }
|