657 lines
18 KiB
C
657 lines
18 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1994 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
detect.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module contains the code that controls the PCMCIA slots.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Bob Rinne (BobRi) 3-Nov-1994
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
Kernel mode
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
// #include <stddef.h>
|
|||
|
#include "ntddk.h"
|
|||
|
#include "string.h"
|
|||
|
#include "pcmcia.h"
|
|||
|
#include "card.h"
|
|||
|
#include "extern.h"
|
|||
|
#include <stdarg.h>
|
|||
|
#include "stdio.h"
|
|||
|
#include "tuple.h"
|
|||
|
|
|||
|
#ifdef POOL_TAGGING
|
|||
|
#undef ExAllocatePool
|
|||
|
#define ExAllocatePool(a,b) ExAllocatePoolWithTag(a,b,'cmcP')
|
|||
|
#endif
|
|||
|
|
|||
|
#define WINDOW_SIZE (132 * 1024)
|
|||
|
|
|||
|
#ifdef ALLOC_PRAGMA
|
|||
|
#pragma alloc_text(INIT,PcmciaAllocateOpenMemoryWindow)
|
|||
|
#pragma alloc_text(INIT,PcmciaDetectMca)
|
|||
|
#pragma alloc_text(INIT,PcmciaDetectSpecialHardware)
|
|||
|
#endif
|
|||
|
|
|||
|
PUCHAR
|
|||
|
PcmciaAllocateOpenMemoryWindow(
|
|||
|
IN PDEVICE_EXTENSION DeviceExtension,
|
|||
|
IN ULONG Start,
|
|||
|
IN PULONG Mapped,
|
|||
|
IN PULONG Physical
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Search the 640K to 1MB region for an open area to be used
|
|||
|
for mapping PCCARD attribute memory.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Start - not used.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
A physical address for the window to the card or zero meaning
|
|||
|
there is no opening.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
#define NUMBER_OF_TEST_BYTES 5
|
|||
|
PHYSICAL_ADDRESS physicalMemoryAddress;
|
|||
|
PHYSICAL_ADDRESS halMemoryAddress;
|
|||
|
BOOLEAN translated;
|
|||
|
ULONG untranslatedAddress;
|
|||
|
PUCHAR memoryAddress;
|
|||
|
PUCHAR bogus;
|
|||
|
ULONG addressSpace;
|
|||
|
ULONG index;
|
|||
|
UCHAR memory[NUMBER_OF_TEST_BYTES];
|
|||
|
|
|||
|
*Mapped = FALSE;
|
|||
|
|
|||
|
if (DeviceExtension->PhysicalBase) {
|
|||
|
untranslatedAddress = DeviceExtension->PhysicalBase;
|
|||
|
} else {
|
|||
|
untranslatedAddress = 0xd0000;
|
|||
|
}
|
|||
|
|
|||
|
for (/* nothing */; untranslatedAddress < 0xFF000; untranslatedAddress += 0x4000) {
|
|||
|
|
|||
|
if (untranslatedAddress == 0xc0000) {
|
|||
|
|
|||
|
//
|
|||
|
// This is VGA. Keep this test if the for loop should
|
|||
|
// ever change.
|
|||
|
//
|
|||
|
|
|||
|
continue;
|
|||
|
}
|
|||
|
addressSpace = 0;
|
|||
|
physicalMemoryAddress.LowPart = untranslatedAddress;
|
|||
|
physicalMemoryAddress.HighPart = 0;
|
|||
|
|
|||
|
translated = HalTranslateBusAddress(Isa,
|
|||
|
0,
|
|||
|
physicalMemoryAddress,
|
|||
|
&addressSpace,
|
|||
|
&halMemoryAddress);
|
|||
|
|
|||
|
if (!translated) {
|
|||
|
|
|||
|
//
|
|||
|
// HAL doesn't like this translation
|
|||
|
//
|
|||
|
|
|||
|
continue;
|
|||
|
}
|
|||
|
if (addressSpace) {
|
|||
|
memoryAddress = (PUCHAR) halMemoryAddress.LowPart;
|
|||
|
} else {
|
|||
|
memoryAddress = MmMapIoSpace(halMemoryAddress, WINDOW_SIZE, FALSE);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Test the memory window to determine if it is a BIOS, video
|
|||
|
// memory, or open memory. Only want to keep the window if it
|
|||
|
// is not being used by something else.
|
|||
|
//
|
|||
|
|
|||
|
for (index = 0; index < NUMBER_OF_TEST_BYTES; index++) {
|
|||
|
memory[index] = READ_REGISTER_UCHAR(memoryAddress + index);
|
|||
|
if (index) {
|
|||
|
if (memory[index] != memory[index - 1]) {
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (index == NUMBER_OF_TEST_BYTES) {
|
|||
|
|
|||
|
//
|
|||
|
// There isn't a BIOS here
|
|||
|
//
|
|||
|
|
|||
|
UCHAR memoryPattern[NUMBER_OF_TEST_BYTES];
|
|||
|
BOOLEAN changed = FALSE;
|
|||
|
|
|||
|
//
|
|||
|
// Check for video memory - open memory should always remain
|
|||
|
// the same regardless what the changes are. Change the
|
|||
|
// pattern previously found.
|
|||
|
//
|
|||
|
|
|||
|
for (index = 0; index < NUMBER_OF_TEST_BYTES; index++) {
|
|||
|
memoryPattern[index] = ~memory[index];
|
|||
|
WRITE_REGISTER_UCHAR(memoryAddress + index,
|
|||
|
memoryPattern[index]);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// See if the pattern in memory changed.
|
|||
|
// Some system exhibit a problem where the memory pattern
|
|||
|
// seems to be cached. If this code is debugged it will
|
|||
|
// work as expected, but if it is run normally it will
|
|||
|
// always return that the memory changed. This random
|
|||
|
// wandering seems to remove this problem.
|
|||
|
//
|
|||
|
|
|||
|
for (index = 0; index < NUMBER_OF_TEST_BYTES; index++) {
|
|||
|
memoryPattern[index] = 0;
|
|||
|
}
|
|||
|
bogus = ExAllocatePool(NonPagedPool, 64 * 1024);
|
|||
|
|
|||
|
if (bogus) {
|
|||
|
for (index = 0; index < 64 * 1024; index++) {
|
|||
|
bogus[index] = 0;
|
|||
|
}
|
|||
|
ExFreePool(bogus);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Now go off and do the actual check to see if the memory
|
|||
|
// changed.
|
|||
|
//
|
|||
|
|
|||
|
for (index = 0; index < NUMBER_OF_TEST_BYTES; index++) {
|
|||
|
|
|||
|
if ((memoryPattern[index] = READ_REGISTER_UCHAR(memoryAddress + index)) != memory[index]) {
|
|||
|
|
|||
|
//
|
|||
|
// It changed - this is not an area of open memory
|
|||
|
//
|
|||
|
|
|||
|
changed = TRUE;
|
|||
|
}
|
|||
|
WRITE_REGISTER_UCHAR(memoryAddress + index,
|
|||
|
memory[index]);
|
|||
|
}
|
|||
|
|
|||
|
if (!changed) {
|
|||
|
|
|||
|
//
|
|||
|
// Area isn't a BIOS and didn't change when written.
|
|||
|
// Use this region for the memory window to PCMCIA
|
|||
|
// attribute memory.
|
|||
|
//
|
|||
|
|
|||
|
*Mapped = addressSpace ? FALSE : TRUE;
|
|||
|
*Physical = untranslatedAddress;
|
|||
|
return memoryAddress;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (!addressSpace) {
|
|||
|
MmUnmapIoSpace(memoryAddress, WINDOW_SIZE);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
PcmciaDetectMca(
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Determine if this system is a micro channel system. If it is this
|
|||
|
driver will not load. More importantly this driver will not go through
|
|||
|
its detect sequence which has a tendency to disable processors on NCR
|
|||
|
MP platforms.
|
|||
|
|
|||
|
The method of determining that this is a MicroChannel system is to
|
|||
|
look into the firmware portion of the registry to see if the first
|
|||
|
bus defined on the system is "MCA".
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE if the platform is MCA
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
ULONG resultLength;
|
|||
|
HANDLE handle;
|
|||
|
NTSTATUS status;
|
|||
|
OBJECT_ATTRIBUTES attributes;
|
|||
|
UNICODE_STRING nameString;
|
|||
|
PWCHAR wideChar;
|
|||
|
PKEY_VALUE_FULL_INFORMATION keyValueInformation;
|
|||
|
|
|||
|
RtlInitUnicodeString(&nameString, L"\\Registry\\MACHINE\\HARDWARE\\DESCRIPTION\\System\\MultiFunctionAdapter\\0");
|
|||
|
InitializeObjectAttributes(&attributes,
|
|||
|
&nameString,
|
|||
|
OBJ_CASE_INSENSITIVE,
|
|||
|
NULL,
|
|||
|
NULL);
|
|||
|
status = ZwOpenKey(&handle, MAXIMUM_ALLOWED, &attributes);
|
|||
|
|
|||
|
if (NT_SUCCESS(status)) {
|
|||
|
|
|||
|
keyValueInformation = ExAllocatePool(NonPagedPool, 1024);
|
|||
|
if (keyValueInformation) {
|
|||
|
|
|||
|
RtlInitUnicodeString(&nameString, L"Identifier");
|
|||
|
status = ZwQueryValueKey(handle,
|
|||
|
&nameString,
|
|||
|
KeyValueFullInformation,
|
|||
|
keyValueInformation,
|
|||
|
1024,
|
|||
|
&resultLength);
|
|||
|
ZwClose(handle);
|
|||
|
if (NT_SUCCESS(status)) {
|
|||
|
if (keyValueInformation->DataLength != 0) {
|
|||
|
|
|||
|
//
|
|||
|
// Have something to check.
|
|||
|
//
|
|||
|
|
|||
|
wideChar = (PWCHAR) ((PUCHAR) keyValueInformation + keyValueInformation->DataOffset);
|
|||
|
|
|||
|
if ((*wideChar == (WCHAR)'M') &&
|
|||
|
(*(wideChar + 1) == (WCHAR)'C') &&
|
|||
|
(*(wideChar + 2) == (WCHAR)'A')) {
|
|||
|
ExFreePool(keyValueInformation);
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
ExFreePool(keyValueInformation);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
PcmciaDetectDevicePresence(
|
|||
|
IN ULONG IoPortBase,
|
|||
|
IN ULONG Length,
|
|||
|
IN UCHAR DeviceType
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine reads the registers given to see if there is a
|
|||
|
possibility of a device being located at the I/O port address.
|
|||
|
A device's presence is viewed as possible if any of the I/O ports
|
|||
|
return a value other than 0xff.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
IoPortBase - where to start
|
|||
|
Length - how long to read
|
|||
|
DeviceType - type of device that is there. This is used to
|
|||
|
perform special action when looking at I/O ports
|
|||
|
that could be ATA registers.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE - If reading the IoPortBase for Length shows that there
|
|||
|
is a possibility that a device exists at this address.
|
|||
|
FALSE If all registers return FF.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PHYSICAL_ADDRESS address;
|
|||
|
PHYSICAL_ADDRESS cardAddress;
|
|||
|
BOOLEAN somethingThere;
|
|||
|
PUCHAR port;
|
|||
|
UCHAR value;
|
|||
|
ULONG index;
|
|||
|
ULONG addressSpace = 1;
|
|||
|
|
|||
|
address.LowPart = IoPortBase;
|
|||
|
address.HighPart = 0;
|
|||
|
|
|||
|
somethingThere = HalTranslateBusAddress(Isa,
|
|||
|
0,
|
|||
|
address,
|
|||
|
&addressSpace,
|
|||
|
&cardAddress);
|
|||
|
|
|||
|
if (!somethingThere) {
|
|||
|
|
|||
|
//
|
|||
|
// HAL won't translate the address so don't try to use it.
|
|||
|
// Return to the caller that something is there to keep from
|
|||
|
// using this address.
|
|||
|
//
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
somethingThere = FALSE;
|
|||
|
if (addressSpace) {
|
|||
|
port = (PUCHAR) cardAddress.LowPart;
|
|||
|
} else {
|
|||
|
port = MmMapIoSpace(cardAddress,
|
|||
|
Length,
|
|||
|
FALSE);
|
|||
|
}
|
|||
|
|
|||
|
if (DeviceType == PCCARD_TYPE_ATA) {
|
|||
|
|
|||
|
//
|
|||
|
// Some ATA devices get into an inconsistent state if all
|
|||
|
// of the registers are touched here so this code performs
|
|||
|
// an ATA detection sequence instead of reading ports.
|
|||
|
//
|
|||
|
|
|||
|
value = READ_PORT_UCHAR(port + 2);
|
|||
|
if ((value == 0xFF) || (value == 0xB0)) {
|
|||
|
|
|||
|
WRITE_PORT_UCHAR(port + 2, 0xAA);
|
|||
|
|
|||
|
//
|
|||
|
// Check if indentifier can be read back.
|
|||
|
//
|
|||
|
|
|||
|
if (READ_PORT_UCHAR(port + 2) == 0xAA) {
|
|||
|
somethingThere = TRUE;
|
|||
|
}
|
|||
|
} else {
|
|||
|
somethingThere = TRUE;
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
for (index = 0; index < Length; index++) {
|
|||
|
value = READ_PORT_UCHAR(port + index);
|
|||
|
if (value != 0xFF) {
|
|||
|
|
|||
|
//
|
|||
|
// PowerPC based systems return B0 for bytes that are
|
|||
|
// not mapped to something.
|
|||
|
//
|
|||
|
|
|||
|
if (value != 0xb0) {
|
|||
|
somethingThere = TRUE;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (somethingThere) {
|
|||
|
if (Length > 3) {
|
|||
|
|
|||
|
//
|
|||
|
// If the requested length of the port range is greater
|
|||
|
// than three. Check to see if all ports in the range
|
|||
|
// are the same. If they are, then assume that nothing
|
|||
|
// is in the range.
|
|||
|
//
|
|||
|
|
|||
|
somethingThere = FALSE;
|
|||
|
value = READ_PORT_UCHAR(port);
|
|||
|
for (index = 0; index < Length; index++) {
|
|||
|
if (value != READ_PORT_UCHAR(port + index)) {
|
|||
|
somethingThere = TRUE;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (!addressSpace) {
|
|||
|
MmUnmapIoSpace(port, Length);
|
|||
|
}
|
|||
|
|
|||
|
return somethingThere;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
struct _BIOS_SearchTable {
|
|||
|
ULONG BIOSLocation;
|
|||
|
PUCHAR BIOSString;
|
|||
|
ULONG AddedIrqMask;
|
|||
|
ULONG MemoryBase;
|
|||
|
};
|
|||
|
|
|||
|
struct _BIOS_SearchTable BIOS_SearchTable[] = {
|
|||
|
{0xe0000, "OPYRIGHT IBM", (1 << 10), 0},
|
|||
|
{0xf0eb0, "opyright 1993 Toshiba", 0, 0xd8000},
|
|||
|
{0, NULL, 0, 0}
|
|||
|
};
|
|||
|
|
|||
|
VOID
|
|||
|
PcmciaDetectSpecialHardware(
|
|||
|
IN PDEVICE_EXTENSION DeviceExtension
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine looks for certain platform specific issues related to interrupts.
|
|||
|
Currently this is done by a scan for BIOS strings to locate IBM 755 laptops and
|
|||
|
avoid use of IRQ 10.
|
|||
|
|
|||
|
Future work will be to add the Windows 95 interrupt detection code here - or
|
|||
|
share this responsibility with ntdetect.com.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
DeviceExtension - locates the interrupt mask and the base of all configuration
|
|||
|
information.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
#define MEMORY_COMPARE_SIZE 100
|
|||
|
#define MEMORY_FUDGE 8
|
|||
|
struct _BIOS_SearchTable *entry;
|
|||
|
PUCHAR memoryAddress;
|
|||
|
PUCHAR mp;
|
|||
|
PUCHAR cp;
|
|||
|
PUCHAR allocBase;
|
|||
|
ULONG addressSpace;
|
|||
|
ULONG index;
|
|||
|
ULONG resultLength;
|
|||
|
BOOLEAN somethingThere;
|
|||
|
BOOLEAN found;
|
|||
|
HANDLE handle;
|
|||
|
NTSTATUS status;
|
|||
|
PHYSICAL_ADDRESS address;
|
|||
|
PHYSICAL_ADDRESS halMemoryAddress;
|
|||
|
OBJECT_ATTRIBUTES attributes;
|
|||
|
UNICODE_STRING nameString;
|
|||
|
PWCHAR wideChar;
|
|||
|
PKEY_VALUE_FULL_INFORMATION keyValueInformation;
|
|||
|
|
|||
|
allocBase = ExAllocatePool(NonPagedPool, MEMORY_COMPARE_SIZE + MEMORY_FUDGE);
|
|||
|
if (!allocBase) {
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
found = FALSE;
|
|||
|
for (entry = BIOS_SearchTable; entry->BIOSLocation; entry++) {
|
|||
|
|
|||
|
addressSpace = 0;
|
|||
|
address.LowPart = entry->BIOSLocation;
|
|||
|
address.HighPart = 0;
|
|||
|
somethingThere = HalTranslateBusAddress(Isa,
|
|||
|
0,
|
|||
|
address,
|
|||
|
&addressSpace,
|
|||
|
&halMemoryAddress);
|
|||
|
|
|||
|
if (!somethingThere) {
|
|||
|
|
|||
|
//
|
|||
|
// HAL won't translate the address so don't try to use it.
|
|||
|
//
|
|||
|
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
if (addressSpace) {
|
|||
|
memoryAddress = (PUCHAR) halMemoryAddress.LowPart;
|
|||
|
} else {
|
|||
|
memoryAddress = MmMapIoSpace(halMemoryAddress, MEMORY_COMPARE_SIZE + MEMORY_FUDGE, FALSE);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Copy the BIOS string to a local buffer and free BIOS map.
|
|||
|
//
|
|||
|
|
|||
|
for (cp = allocBase, mp = memoryAddress, index = 0;
|
|||
|
index < MEMORY_COMPARE_SIZE;
|
|||
|
cp++, mp++, index++) {
|
|||
|
|
|||
|
*cp = READ_REGISTER_UCHAR(mp);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Insure e-o-s termination.
|
|||
|
//
|
|||
|
|
|||
|
for (index = 0; index < MEMORY_FUDGE; index++, cp++) {
|
|||
|
*cp = '\0';
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Done with mapped memory
|
|||
|
//
|
|||
|
|
|||
|
if (!addressSpace) {
|
|||
|
MmUnmapIoSpace(memoryAddress, MEMORY_COMPARE_SIZE + MEMORY_FUDGE);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Search for string.
|
|||
|
//
|
|||
|
|
|||
|
if (strstr(allocBase, entry->BIOSString)) {
|
|||
|
|
|||
|
//
|
|||
|
// string is there.
|
|||
|
//
|
|||
|
|
|||
|
if (entry->AddedIrqMask) {
|
|||
|
DeviceExtension->AllocatedIrqlMask |= entry->AddedIrqMask;
|
|||
|
}
|
|||
|
|
|||
|
if (entry->MemoryBase) {
|
|||
|
DeviceExtension->PhysicalBase = entry->MemoryBase;
|
|||
|
}
|
|||
|
found = TRUE;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
ExFreePool(allocBase);
|
|||
|
|
|||
|
if (!found) {
|
|||
|
|
|||
|
//
|
|||
|
// Check if the hardware is PPC...
|
|||
|
//
|
|||
|
|
|||
|
RtlInitUnicodeString(&nameString,
|
|||
|
L"\\Registry\\MACHINE\\HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0");
|
|||
|
InitializeObjectAttributes(&attributes,
|
|||
|
&nameString,
|
|||
|
OBJ_CASE_INSENSITIVE,
|
|||
|
NULL,
|
|||
|
NULL);
|
|||
|
|
|||
|
status = ZwOpenKey(&handle, MAXIMUM_ALLOWED, &attributes);
|
|||
|
|
|||
|
if (NT_SUCCESS(status)) {
|
|||
|
keyValueInformation = ExAllocatePool(NonPagedPool, 1024);
|
|||
|
if (keyValueInformation) {
|
|||
|
|
|||
|
RtlInitUnicodeString(&nameString, L"Identifier");
|
|||
|
status = ZwQueryValueKey(handle,
|
|||
|
&nameString,
|
|||
|
KeyValueFullInformation,
|
|||
|
keyValueInformation,
|
|||
|
1024,
|
|||
|
&resultLength);
|
|||
|
ZwClose(handle);
|
|||
|
if (NT_SUCCESS(status)) {
|
|||
|
if (keyValueInformation->DataLength != 0) {
|
|||
|
|
|||
|
//
|
|||
|
// Have something to check.
|
|||
|
//
|
|||
|
|
|||
|
wideChar = (PWCHAR) ((PUCHAR) keyValueInformation + keyValueInformation->DataOffset);
|
|||
|
|
|||
|
if ((*wideChar == (WCHAR)'P') &&
|
|||
|
(*(wideChar + 1) == (WCHAR)'o') &&
|
|||
|
(*(wideChar + 2) == (WCHAR)'w') &&
|
|||
|
(*(wideChar + 3) == (WCHAR)'e') &&
|
|||
|
(*(wideChar + 4) == (WCHAR)'r') &&
|
|||
|
(*(wideChar + 5) == (WCHAR)'P') &&
|
|||
|
(*(wideChar + 6) == (WCHAR)'C')) {
|
|||
|
|
|||
|
//
|
|||
|
// Disable Interrupt 10 from the mask
|
|||
|
//
|
|||
|
|
|||
|
DeviceExtension->AllocatedIrqlMask |= (1 << 10);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
ExFreePool(keyValueInformation);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Search for registry override of memory window physical address
|
|||
|
//
|
|||
|
|
|||
|
PcmciaRegistryMemoryWindow(DeviceExtension);
|
|||
|
|
|||
|
}
|