/*++ Copyright (c) 1990, 1991 Microsoft Corporation Module Name: hwapm.c Abstract: Author: Environment: Real mode. Revision History: --*/ #include "hwdetect.h" #include #include "apm.h" #include 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; }