NT4/private/ntos/dd/pcmcia/registry.c

2487 lines
83 KiB
C
Raw Normal View History

2001-01-01 00:00:00 +01:00
/*++
Copyright (c) 1994 Microsoft Corporation
Module Name:
registry.c
Abstract:
This module contains the code that manipulates the ARC firmware
tree and other elements in the registry.
Author:
Bob Rinne (BobRi) 15-Oct-1994
Environment:
Kernel mode
Revision History :
--*/
// #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
//
// Definitions needed prior to alloc_text statements.
//
NTSTATUS
PcmciaInterfaceTypeCallBack(
IN PVOID Context,
IN PUNICODE_STRING PathName,
IN INTERFACE_TYPE BusType,
IN ULONG BusNumber,
IN PKEY_VALUE_FULL_INFORMATION *BusInformation,
IN CONFIGURATION_TYPE ControllerType,
IN ULONG ControllerNumber,
IN PKEY_VALUE_FULL_INFORMATION *ControllerInformation,
IN CONFIGURATION_TYPE PeripheralType,
IN ULONG PeripheralNumber,
IN PKEY_VALUE_FULL_INFORMATION *PeripheralInformation
);
NTSTATUS
PcmciaSerialCallback(
IN PVOID Context,
IN PUNICODE_STRING PathName,
IN INTERFACE_TYPE BusType,
IN ULONG BusNumber,
IN PKEY_VALUE_FULL_INFORMATION *BusInformation,
IN CONFIGURATION_TYPE ControllerType,
IN ULONG ControllerNumber,
IN PKEY_VALUE_FULL_INFORMATION *ControllerInformation,
IN CONFIGURATION_TYPE PeripheralType,
IN ULONG PeripheralNumber,
IN PKEY_VALUE_FULL_INFORMATION *PeripheralInformation
);
NTSTATUS
PcmciaPointerCallback(
IN PVOID Context,
IN PUNICODE_STRING PathName,
IN INTERFACE_TYPE BusType,
IN ULONG BusNumber,
IN PKEY_VALUE_FULL_INFORMATION *BusInformation,
IN CONFIGURATION_TYPE ControllerType,
IN ULONG ControllerNumber,
IN PKEY_VALUE_FULL_INFORMATION *ControllerInformation,
IN CONFIGURATION_TYPE PeripheralType,
IN ULONG PeripheralNumber,
IN PKEY_VALUE_FULL_INFORMATION *PeripheralInformation
);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT,PcmciaInterfaceTypeCallBack)
#pragma alloc_text(INIT,PcmciaSerialCallback)
#pragma alloc_text(INIT,PcmciaPointerCallback)
#pragma alloc_text(INIT,PcmciaProcessFirmwareTree)
#pragma alloc_text(INIT,PcmciaConstructSerialTreeEntry)
#pragma alloc_text(INIT,PcmciaConstructFirmwareEntry)
#pragma alloc_text(INIT,PcmciaConstructRegistryEntry)
#pragma alloc_text(INIT,PcmciaReportResources)
#pragma alloc_text(INIT,PcmciaUnReportResources)
#pragma alloc_text(INIT,PcmciaCheckSerialRegistryInformation)
#pragma alloc_text(INIT,PcmciaRegistryMemoryWindow)
#endif
NTSTATUS
PcmciaInterfaceTypeCallBack(
IN PVOID Context,
IN PUNICODE_STRING PathName,
IN INTERFACE_TYPE BusType,
IN ULONG BusNumber,
IN PKEY_VALUE_FULL_INFORMATION *BusInformation,
IN CONFIGURATION_TYPE ControllerType,
IN ULONG ControllerNumber,
IN PKEY_VALUE_FULL_INFORMATION *ControllerInformation,
IN CONFIGURATION_TYPE PeripheralType,
IN ULONG PeripheralNumber,
IN PKEY_VALUE_FULL_INFORMATION *PeripheralInformation
)
/*++
Routine Description:
This routine is called to check if a particular item
is present in the registry.
Arguments:
Context - Pointer to a boolean.
PathName - unicode registry path.
BusType - Internal, Isa, ...
BusNumber - Which bus if we are on a multibus system.
BusInformation - Configuration information about the bus. Not Used.
ControllerType - serial or ata disk.
ControllerNumber - Which controller if there is more than one
controller in the system.
ControllerInformation - Array of pointers to the three pieces of
registry information.
PeripheralType - Undefined for this call.
PeripheralNumber - Undefined for this call.
PeripheralInformation - Undefined for this call.
Return Value:
STATUS_SUCCESS
--*/
{
PDEVICE_EXTENSION deviceExtension = Context;
deviceExtension->InterfaceType = BusType;
deviceExtension->BusNumber = BusNumber;
return STATUS_SUCCESS;
}
NTSTATUS
PcmciaPointerCallback(
IN PVOID Context,
IN PUNICODE_STRING PathName,
IN INTERFACE_TYPE BusType,
IN ULONG BusNumber,
IN PKEY_VALUE_FULL_INFORMATION *BusInformation,
IN CONFIGURATION_TYPE ControllerType,
IN ULONG ControllerNumber,
IN PKEY_VALUE_FULL_INFORMATION *ControllerInformation,
IN CONFIGURATION_TYPE PeripheralType,
IN ULONG PeripheralNumber,
IN PKEY_VALUE_FULL_INFORMATION *PeripheralInformation
)
/*++
Routine Description:
This routine is used to acquire the IRQ configuration information
for each pointer controller or device found by the firmware
Arguments:
Context - Pointer to the device extension.
PathName - unicode registry path.
BusType - Internal, Isa, ...
BusNumber - Which bus if we are on a multibus system.
BusInformation - Configuration information about the bus. Not Used.
ControllerType - serial or ata disk.
ControllerNumber - Which controller if there is more than one
controller in the system.
ControllerInformation - Array of pointers to the three pieces of
registry information.
PeripheralType - Undefined for this call.
PeripheralNumber - Undefined for this call.
PeripheralInformation - Undefined for this call.
Return Value:
STATUS_SUCCESS if everything went ok, or STATUS_INSUFFICIENT_RESOURCES
if it couldn't map the base csr or acquire the device object, or
all of the resource information couldn't be acquired.
--*/
{
PDEVICE_EXTENSION deviceExtension = Context;
PCM_FULL_RESOURCE_DESCRIPTOR controllerData;
PCM_PARTIAL_RESOURCE_DESCRIPTOR partialData;
ULONG index;
if (!ControllerInformation[IoQueryDeviceConfigurationData]->DataLength) {
return STATUS_SUCCESS;
}
//
// Process all of the partial descriptors to extract the
// interrupts already in use.
//
controllerData = (PCM_FULL_RESOURCE_DESCRIPTOR)
(((PUCHAR)ControllerInformation[IoQueryDeviceConfigurationData]) +
ControllerInformation[IoQueryDeviceConfigurationData]->DataOffset);
for (index = 0; index < controllerData->PartialResourceList.Count; index++) {
partialData = &controllerData->PartialResourceList.PartialDescriptors[index];
switch (partialData->Type) {
case CmResourceTypeInterrupt:
deviceExtension->AllocatedIrqlMask |= (1 << partialData->u.Interrupt.Level);
break;
default:
break;
}
}
return STATUS_SUCCESS;
}
NTSTATUS
PcmciaSerialCallback(
IN PVOID Context,
IN PUNICODE_STRING PathName,
IN INTERFACE_TYPE BusType,
IN ULONG BusNumber,
IN PKEY_VALUE_FULL_INFORMATION *BusInformation,
IN CONFIGURATION_TYPE ControllerType,
IN ULONG ControllerNumber,
IN PKEY_VALUE_FULL_INFORMATION *ControllerInformation,
IN CONFIGURATION_TYPE PeripheralType,
IN ULONG PeripheralNumber,
IN PKEY_VALUE_FULL_INFORMATION *PeripheralInformation
)
/*++
Routine Description:
This routine is used to acquire the I/O and IRQ configuration
information for each serial controller found by the firmware
Arguments:
Context - Pointer to the device extension.
PathName - unicode registry path.
BusType - Internal, Isa, ...
BusNumber - Which bus if we are on a multibus system.
BusInformation - Configuration information about the bus. Not Used.
ControllerType - serial or ata disk.
ControllerNumber - Which controller if there is more than one
controller in the system.
ControllerInformation - Array of pointers to the three pieces of
registry information.
PeripheralType - Undefined for this call.
PeripheralNumber - Undefined for this call.
PeripheralInformation - Undefined for this call.
Return Value:
STATUS_SUCCESS if everything went ok, or STATUS_INSUFFICIENT_RESOURCES
if it couldn't map the base csr or acquire the device object, or
all of the resource information couldn't be acquired.
--*/
{
PDEVICE_EXTENSION deviceExtension = Context;
PCM_FULL_RESOURCE_DESCRIPTOR controllerData;
PCM_PARTIAL_RESOURCE_DESCRIPTOR partialData;
PFIRMWARE_CONFIGURATION firmwareEntry;
PVOID buffer;
ULONG index;
//
// Sanity check that there is data in the given information.
//
if (!ControllerInformation[IoQueryDeviceConfigurationData]->DataLength) {
return STATUS_SUCCESS;
}
firmwareEntry = ExAllocatePool(NonPagedPool, sizeof(FIRMWARE_CONFIGURATION));
if (!firmwareEntry) {
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlZeroMemory(firmwareEntry, sizeof(FIRMWARE_CONFIGURATION));
//
// Process all of the partial descriptors to extract the I/O
// ports and interrupts already in use.
//
controllerData = (PCM_FULL_RESOURCE_DESCRIPTOR)
(((PUCHAR)ControllerInformation[IoQueryDeviceConfigurationData]) +
ControllerInformation[IoQueryDeviceConfigurationData]->DataOffset);
for (index = 0; index < controllerData->PartialResourceList.Count; index++) {
partialData = &controllerData->PartialResourceList.PartialDescriptors[index];
switch (partialData->Type) {
case CmResourceTypePort:
//
// Save the two Io port bases.
//
if (firmwareEntry->NumberBases < 2) {
firmwareEntry->PortBases[firmwareEntry->NumberBases] = partialData->u.Port.Start.LowPart;
firmwareEntry->NumberBases++;
}
break;
case CmResourceTypeInterrupt:
{
UNICODE_STRING path;
//
// Remember serial port interrupts.
//
deviceExtension->AllocatedIrqlMask |= (1 << partialData->u.Interrupt.Level);
firmwareEntry->Irq = partialData->u.Interrupt.Level;
break;
}
default:
break;
}
}
firmwareEntry->ControllerType = ControllerType;
firmwareEntry->ControllerNumber = ControllerNumber;
firmwareEntry->InterfaceType = BusType;
firmwareEntry->BusNumber = BusNumber;
firmwareEntry->Next = deviceExtension->FirmwareList;
deviceExtension->FirmwareList = firmwareEntry;
return STATUS_SUCCESS;
}
VOID
PcmciaProcessFirmwareTree(
IN PDEVICE_EXTENSION DeviceExtension
)
/*++
Routine Description:
Query the information in the firmware tree to know what
serial ports were located. This will cause a FirmwareList
to be created on the device extention passed.
Arguments:
DeviceExtension - extension for the pcmcia controller
Return Value:
None
--*/
{
PRTL_QUERY_REGISTRY_TABLE serviceParams;
INTERFACE_TYPE interfaceType;
CONFIGURATION_TYPE sc;
UNICODE_STRING servicePath;
NTSTATUS status;
ULONG atapiEnabled;
ULONG disabled = 4;
#ifdef ITEMS_TO_QUERY
#undef ITEMS_TO_QUERY
#endif
#define ITEMS_TO_QUERY 2
//
// Determine the bus for serial firmware tree entries.
//
DeviceExtension->InterfaceType = Internal;
for (interfaceType = 0; interfaceType < MaximumInterfaceType; interfaceType++) {
if (interfaceType != Internal) {
IoQueryDeviceDescription(&interfaceType,
NULL,
NULL,
NULL,
NULL,
NULL,
PcmciaInterfaceTypeCallBack,
DeviceExtension);
if (DeviceExtension->InterfaceType != Internal) {
break;
}
}
}
if (DeviceExtension->InterfaceType == Internal) {
DebugPrint((PCMCIA_DEBUG_FAIL, "PCMCIA: did not find bus type\n"));
DeviceExtension->InterfaceType = Isa;
DeviceExtension->BusNumber = 0;
}
//
// Locate all firmware device information and save its resource usage.
//
for (interfaceType = 0; interfaceType < MaximumInterfaceType; interfaceType++) {
//
// Locate any pointer devices on this interface type.
//
sc = PointerController;
IoQueryDeviceDescription(&interfaceType,
NULL,
&sc,
NULL,
NULL,
NULL,
PcmciaPointerCallback,
DeviceExtension);
sc = PointerPeripheral;
IoQueryDeviceDescription(&interfaceType,
NULL,
&sc,
NULL,
NULL,
NULL,
PcmciaPointerCallback,
DeviceExtension);
//
// Locate the serial controllers.
//
sc = SerialController;
IoQueryDeviceDescription(&interfaceType,
NULL,
&sc,
NULL,
NULL,
NULL,
PcmciaSerialCallback,
DeviceExtension);
}
//
// Determine if ATAPI is the ATA disk driver of choice and remember this
// for ATA PCCARDs.
//
DeviceExtension->AtapiPresent = 0;
RtlInitUnicodeString(&servicePath, NULL);
servicePath.MaximumLength = 1024;
servicePath.Buffer = ExAllocatePool(NonPagedPool, 1024);
if (!servicePath.Buffer) {
return;
}
serviceParams = ExAllocatePool(NonPagedPool,
sizeof(RTL_QUERY_REGISTRY_TABLE)*ITEMS_TO_QUERY);
if (!serviceParams) {
ExFreePool(servicePath.Buffer);
return;
}
RtlZeroMemory(servicePath.Buffer, 1024);
RtlZeroMemory(serviceParams,
(sizeof(RTL_QUERY_REGISTRY_TABLE)*ITEMS_TO_QUERY));
//
// All memory allocated and zeroed - set up path and request to see if ATAPI
// is to be started.
//
RtlAppendUnicodeToString(&servicePath,
L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services\\Atapi");
serviceParams[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
serviceParams[0].Name = L"Start";
serviceParams[0].EntryContext = &atapiEnabled;
serviceParams[0].DefaultType = REG_DWORD;
serviceParams[0].DefaultData = &disabled;
serviceParams[0].DefaultLength = sizeof(ULONG);
status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
servicePath.Buffer,
serviceParams,
NULL,
NULL);
//
// NOTE: This is pretty gross because there is hardcoded knowledge about the meaning
// of the start value in the services key.
//
DeviceExtension->AtapiPresent = (atapiEnabled == 4) ? FALSE : TRUE;
//
// Free all allocations
//
ExFreePool(serviceParams);
ExFreePool(servicePath.Buffer);
}
VOID
PcmciaConstructSerialTreeEntry(
IN PDEVICE_EXTENSION DeviceExtension,
IN PSOCKET_CONFIGURATION SocketConfiguration
)
/*++
Routine Description:
Construct an entry in the firmware tree so the serial device
driver will recognize the serial port for the PCCARD.
Arguments:
DeviceExtension - extension for the pcmcia controller
SocketConfiguration - the configuration for a particular serial PCCARD.
Return Value:
None
--*/
{
PWCHAR wideChar;
ULONG count;
NTSTATUS status;
OBJECT_ATTRIBUTES objectAttributes;
UNICODE_STRING unicodeName;
PUNICODE_STRING unicodeNamePtr;
HANDLE handle;
ULONG disposition;
ULONG busNumber;
INTERFACE_TYPE interface;
BOOLEAN isa;
PFIRMWARE_CONFIGURATION firmwareEntry;
ULONG buffer[20];
PCM_SERIAL_DEVICE_DATA serialData;
PCM_FULL_RESOURCE_DESCRIPTOR controllerData;
PCM_PARTIAL_RESOURCE_DESCRIPTOR partialData;
//
// Construct the registry path for the serial firmware information
//
if (!DeviceExtension->FirmwareRegistryPath.Buffer) {
//
// No comm ports present - construct the tree from scratch
// using MultifunctionAdapter as the base.
//
unicodeNamePtr = &unicodeName;
unicodeNamePtr->Length = 0;
unicodeNamePtr->MaximumLength = 256 * sizeof(WCHAR);
unicodeNamePtr->Buffer = ExAllocatePool(NonPagedPool,
unicodeNamePtr->MaximumLength);
if (!unicodeNamePtr->Buffer) {
return;
}
RtlAppendUnicodeToString(unicodeNamePtr,
L"\\Registry\\Machine\\Hardware\\Description\\System\\");
if (DeviceExtension->InterfaceType == Eisa) {
RtlAppendUnicodeToString(unicodeNamePtr,
L"EisaAdapter\\0");
wideChar = NULL;
} else {
RTL_QUERY_REGISTRY_TABLE socketParams[2];
WCHAR identifierBuff[10];
UNICODE_STRING identifierString;
UNICODE_STRING busNumberString;
USHORT savedLen;
BOOLEAN isaFound = FALSE;
ULONG busNumber = 0;
RtlAppendUnicodeToString(unicodeNamePtr,
L"MultifunctionAdapter\\");
//
// Get the length of the existing string and set up the bus number unicode
// string to locate the memory at the end of this string.
//
savedLen = unicodeNamePtr->Length;
busNumberString.Length = 0;
busNumberString.MaximumLength = sizeof(WCHAR)*4;
busNumberString.Buffer = unicodeNamePtr->Buffer;
busNumberString.Buffer+= ((unicodeNamePtr->Length / sizeof(WCHAR)));
//
// Append the bus number to the unicode name - update the unicode name
// string to include the number.
//
RtlIntegerToUnicodeString(busNumber,
10,
&busNumberString);
unicodeNamePtr->Length = savedLen + busNumberString.Length;
//
// Locate the ISA bus number.
//
identifierString.Length = 0;
identifierString.MaximumLength = sizeof(WCHAR)*10;
identifierString.Buffer = identifierBuff;
RtlZeroMemory(socketParams, (sizeof(RTL_QUERY_REGISTRY_TABLE)*2));
socketParams[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
socketParams[0].Name = L"Identifier";
socketParams[0].EntryContext = &identifierString;
socketParams[0].DefaultType = REG_SZ;
socketParams[0].DefaultData = L"NON";
socketParams[0].DefaultLength = sizeof(WCHAR)*20;
//
// Loop through all of the buses and get the bus type from the
// "Identifier" value.
//
while (NT_SUCCESS(RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
unicodeNamePtr->Buffer,
socketParams,
NULL,
NULL))) {
//
// Is this the ISA bus
//
if (RtlCompareMemory(identifierBuff, L"ISA", 8) == 8) {
isaFound = TRUE;
break;
}
//
// Increment to the next bus number
//
busNumber++;
RtlIntegerToUnicodeString(busNumber,
10,
&busNumberString);
unicodeNamePtr->Length = savedLen + busNumberString.Length;
}
//
// If no ISA bus found just quit
//
if (!isaFound) {
ExFreePool(unicodeNamePtr->Buffer);
return;
}
}
RtlAppendUnicodeToString(unicodeNamePtr,
L"\\SerialController");
RtlZeroMemory(&objectAttributes, sizeof(OBJECT_ATTRIBUTES));
InitializeObjectAttributes(&objectAttributes,
unicodeNamePtr,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
//
// See if the serial key is present.
//
if (NT_SUCCESS(ZwOpenKey(&handle, MAXIMUM_ALLOWED, &objectAttributes))) {
ZwClose(handle);
} else {
//
// Not present, create one.
//
status = ZwCreateKey(&handle,
KEY_READ | KEY_WRITE,
&objectAttributes,
0,
NULL,
REG_OPTION_VOLATILE,
&disposition);
if (!NT_SUCCESS(status)) {
ExFreePool(unicodeNamePtr->Buffer);
return;
}
}
//
// Update the string to look like a firmware entry and save it
// for future use. The code below will update the number to
// reflect the new key name.
//
RtlAppendUnicodeToString(unicodeNamePtr, L"\\0");
DeviceExtension->FirmwareRegistryPath = unicodeName;
} else {
unicodeNamePtr = &DeviceExtension->FirmwareRegistryPath;
}
//
// Count the number of firmware entries found.
//
count = DeviceExtension->SerialNumber;
if (!count) {
if (DeviceExtension->FirmwareList) {
count = 0;
for (firmwareEntry = DeviceExtension->FirmwareList; firmwareEntry; firmwareEntry = firmwareEntry->Next) {
if (firmwareEntry->InterfaceType == DeviceExtension->InterfaceType) {
count++;
}
}
}
}
if (count > 9) {
//
// NOTE:
// Don't support > 9 comm ports at the moment.
//
return;
}
interface = DeviceExtension->InterfaceType;
busNumber = 0;
//
// count is now set to the value that should be placed in the
// firmware tree for this serial port.
//
wideChar = unicodeNamePtr->Buffer;
wideChar += ((unicodeNamePtr->Length / sizeof(WCHAR)) - 1);
*wideChar = (WCHAR) ('0' + count);
DeviceExtension->SerialNumber = count + 1;
//
// Create the registry key.
//
RtlZeroMemory(&objectAttributes, sizeof(OBJECT_ATTRIBUTES));
InitializeObjectAttributes(&objectAttributes,
unicodeNamePtr,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
status = ZwCreateKey(&handle,
KEY_READ | KEY_WRITE,
&objectAttributes,
0,
NULL,
REG_OPTION_VOLATILE,
&disposition);
if (!NT_SUCCESS(status)) {
return;
}
//
// Construct the component Configuration Data.
//
controllerData = (PCM_FULL_RESOURCE_DESCRIPTOR) buffer;
controllerData->InterfaceType = interface;
controllerData->BusNumber = busNumber;
controllerData->PartialResourceList.Version = 1;
controllerData->PartialResourceList.Revision = 2;
controllerData->PartialResourceList.Count = 3;
partialData = &controllerData->PartialResourceList.PartialDescriptors[0];
partialData->Type = CmResourceTypePort;
partialData->ShareDisposition = CmResourceShareDeviceExclusive;
partialData->Flags = CM_RESOURCE_PORT_IO;
partialData->u.Port.Start.QuadPart = (LONGLONG) SocketConfiguration->IoPortBase[0];
partialData->u.Port.Length = SocketConfiguration->IoPortLength[0];
partialData = &controllerData->PartialResourceList.PartialDescriptors[1];
partialData->Type = CmResourceTypeInterrupt;
partialData->ShareDisposition = CmResourceShareDeviceExclusive;
partialData->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
partialData->u.Interrupt.Level = SocketConfiguration->Irq;
partialData->u.Interrupt.Vector = SocketConfiguration->Irq;
partialData->u.Interrupt.Affinity = 0xffffffff;
partialData = &controllerData->PartialResourceList.PartialDescriptors[2];
partialData->Type = CmResourceTypeDeviceSpecific;
partialData->ShareDisposition = CmResourceShareDeviceExclusive;
partialData->Flags = 0;
partialData->u.DeviceSpecificData.DataSize = 8;
partialData->u.DeviceSpecificData.Reserved1 = 0;
partialData->u.DeviceSpecificData.Reserved2 = 0;
//
// Fill in magic numbers
//
serialData = (PCM_SERIAL_DEVICE_DATA)&controllerData->PartialResourceList.PartialDescriptors[3];
serialData->Version = 1;
serialData->Revision = 2;
serialData->BaudClock = 0x1c2000;
//
// Create the KeyValue for this configuration.
//
RtlInitUnicodeString(&unicodeName, L"Configuration Data");
ZwSetValueKey(handle,
&unicodeName,
0,
REG_FULL_RESOURCE_DESCRIPTOR,
controllerData,
18 * sizeof(ULONG));
//
// If this is a multi function modem card, construct the firmware
// entry to inform serial.sys to share the interrupt.
//
if (SocketConfiguration->MultiFunctionModem) {
//
// Use the count variable as the data location for the value
//
count = 1;
//
// Construct the UNICODE name for the value - this goes in the same
// key location as the resource descriptor.
//
RtlInitUnicodeString(&unicodeName, L"Share System Interrupt");
ZwSetValueKey(handle,
&unicodeName,
0,
REG_DWORD,
&count,
sizeof(ULONG));
}
ZwClose(handle);
}
NTSTATUS
PcmciaConstructFirmwareEntry(
IN PDEVICE_EXTENSION DeviceExtension,
IN PSOCKET_CONFIGURATION SocketConfiguration
)
/*++
Routine Description:
Given a socket configuration about to be enabled, construct a
firmware entry with which to remember it such that the resources
will not be allocated twice.
Arguments:
DeviceExtension - the base information for the PCMCIA controller
SocketConfiguration - the configuration about to be made.
Return Values:
SUCCESS or FAILURE
--*/
{
PFIRMWARE_CONFIGURATION firmwareEntry;
firmwareEntry = ExAllocatePool(NonPagedPool, sizeof(FIRMWARE_CONFIGURATION));
if (!firmwareEntry) {
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlZeroMemory(firmwareEntry, sizeof(FIRMWARE_CONFIGURATION));
firmwareEntry->PortBases[0] = SocketConfiguration->IoPortBase[0];
firmwareEntry->PortBases[1] = SocketConfiguration->IoPortBase[1];
firmwareEntry->Irq = SocketConfiguration->Irq;
//
// Link it in the chain
//
firmwareEntry->Next = DeviceExtension->FirmwareList;
DeviceExtension->FirmwareList = firmwareEntry;
return STATUS_SUCCESS;
}
VOID
PcmciaConstructRegistryEntry(
IN PDEVICE_EXTENSION DeviceExtension,
IN PSOCKET_DATA SocketData,
IN PSOCKET_CONFIGURATION SocketConfiguration
)
/*++
Routine Description:
Construct an entry in the volatile portion of the registry
for this configuration. This information may be used later
by drivers when setting up to operate on the PCCARD.
Arguments:
DeviceExtension - the base information for the PCMCIA controller
SocketConfiguration - the configuration about to be made.
Return Values:
None
++*/
{
OBJECT_ATTRIBUTES objectAttributes;
UNICODE_STRING unicodeName;
PUNICODE_STRING unicodeNamePtr;
HANDLE handle;
PUCHAR buffer;
ULONG index;
ULONG count;
NTSTATUS status;
ULONG disposition;
PCM_FULL_RESOURCE_DESCRIPTOR controllerData;
PCM_PARTIAL_RESOURCE_DESCRIPTOR partialData;
if (!(handle = DeviceExtension->ConfigurationHandle)) {
//
// Create the registry key.
//
unicodeNamePtr = &unicodeName;
RtlInitUnicodeString(unicodeNamePtr,
L"\\Registry\\Machine\\Hardware\\Description\\System\\PCMCIA PCCARDs");
RtlZeroMemory(&objectAttributes, sizeof(OBJECT_ATTRIBUTES));
InitializeObjectAttributes(&objectAttributes,
unicodeNamePtr,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
status = ZwCreateKey(&handle,
KEY_READ | KEY_WRITE,
&objectAttributes,
0,
NULL,
REG_OPTION_VOLATILE,
&disposition);
if (!NT_SUCCESS(status)) {
return;
}
DeviceExtension->ConfigurationHandle = handle;
}
buffer = ExAllocatePool(NonPagedPool, 4096);
if (!buffer) {
return;
}
count = 0;
//
// Construct the component Configuration Data.
//
controllerData = (PCM_FULL_RESOURCE_DESCRIPTOR) buffer;
controllerData->InterfaceType = DeviceExtension->InterfaceType;
controllerData->BusNumber = DeviceExtension->BusNumber;
controllerData->PartialResourceList.Version = 1;
controllerData->PartialResourceList.Revision = 2;
//
// Construct partial data for each configuration element
//
partialData = &controllerData->PartialResourceList.PartialDescriptors[count];
partialData->Type = CmResourceTypePort;
partialData->ShareDisposition = CmResourceShareDeviceExclusive;
partialData->Flags = CM_RESOURCE_PORT_IO;
partialData->u.Port.Start.QuadPart = (LONGLONG) SocketConfiguration->IoPortBase[0];
partialData->u.Port.Length = SocketConfiguration->IoPortLength[0];
count++;
if (SocketConfiguration->IoPortBase[1]) {
partialData = &controllerData->PartialResourceList.PartialDescriptors[count];
partialData->Type = CmResourceTypePort;
partialData->ShareDisposition = CmResourceShareDeviceExclusive;
partialData->Flags = CM_RESOURCE_PORT_IO;
partialData->u.Port.Start.QuadPart = (LONGLONG) SocketConfiguration->IoPortBase[1];
partialData->u.Port.Length = SocketConfiguration->IoPortLength[1];
count++;
}
partialData = &controllerData->PartialResourceList.PartialDescriptors[count];
partialData->Type = CmResourceTypeInterrupt;
partialData->ShareDisposition = CmResourceShareDeviceExclusive;
partialData->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
partialData->u.Interrupt.Level = SocketConfiguration->Irq;
partialData->u.Interrupt.Vector = SocketConfiguration->Irq;
partialData->u.Interrupt.Affinity = 0xffffffff;
count++;
for (index = 0; index < MAX_NUMBER_OF_MEMORY_RANGES; index++) {
if (SocketConfiguration->MemoryHostBase[index]) {
partialData = &controllerData->PartialResourceList.PartialDescriptors[count];
partialData->Type = CmResourceTypeMemory;
partialData->ShareDisposition = CmResourceShareDeviceExclusive;
partialData->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
partialData->u.Port.Start.QuadPart = (LONGLONG) SocketConfiguration->MemoryHostBase[index];
partialData->u.Port.Length = SocketConfiguration->MemoryLength[index];
count++;
} else {
//
// No need to continue once one zero entry has been found.
//
break;
}
}
controllerData->PartialResourceList.Count = count;
//
// Create the KeyValue for this configuration.
//
if (SocketData->Instance) {
UNICODE_STRING numberString;
WCHAR numberBuffer[4];
unicodeNamePtr = &unicodeName;
unicodeNamePtr->MaximumLength = 256 * sizeof(WCHAR);
unicodeNamePtr->Length = 0;
unicodeNamePtr->Buffer = ExAllocatePool(NonPagedPool,
unicodeNamePtr->MaximumLength);
if (!unicodeNamePtr->Buffer) {
ExFreePool(buffer);
return;
}
//
// Convert the instance to a unicode string.
//
numberString.MaximumLength = 8;
numberString.Length = 0;
numberString.Buffer = numberBuffer;
RtlIntegerToUnicodeString(SocketData->Instance, 10, &numberString);
//
// Construct the instance name.
//
RtlAppendUnicodeStringToString(unicodeNamePtr, &SocketData->DriverName);
RtlAppendUnicodeStringToString(unicodeNamePtr, &numberString);
} else {
unicodeNamePtr = &SocketData->DriverName;
}
//
// Store the value.
//
ZwSetValueKey(handle,
unicodeNamePtr,
0,
REG_FULL_RESOURCE_DESCRIPTOR,
controllerData,
(ULONG) &controllerData->PartialResourceList.PartialDescriptors[count] - (ULONG) controllerData);
ExFreePool(buffer);
if (SocketData->Instance) {
ExFreePool(unicodeNamePtr->Buffer);
}
}
VOID
PcmciaReportResources(
IN PDEVICE_EXTENSION DeviceExtension,
OUT BOOLEAN *ConflictDetected
)
/*++
Routine Description:
Reports controller resources to the system
Arguments:
DeviceExtension - The controller objects device extension
ConflictDetected - Conflict
Return Value:
none
--*/
{
PCM_RESOURCE_LIST resourceList;
ULONG sizeOfResourceList;
ULONG countOfPartials;
PCM_PARTIAL_RESOURCE_DESCRIPTOR partial;
UNICODE_STRING className;
//
// The built in partial resource list will have at
// least a count of 1:
//
// 1) The base register physical address and it's span.
//
// If an interrupt is claimed it will be added to the list.
// Allocate enough memory to contain the complete list.
//
sizeOfResourceList = sizeof(CM_RESOURCE_LIST) +
(sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) * 2);
resourceList = ExAllocatePool(NonPagedPool,
sizeOfResourceList);
if (!resourceList) {
return;
}
RtlZeroMemory(resourceList, sizeOfResourceList);
//
// Adjust the size in case there is no interrupt.
//
sizeOfResourceList = sizeof(CM_RESOURCE_LIST) +
sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
countOfPartials = 1;
resourceList->Count = 1;
resourceList->List[0].InterfaceType = DeviceExtension->Configuration.InterfaceType;
resourceList->List[0].BusNumber = DeviceExtension->Configuration.BusNumber;
partial = &resourceList->List[0].PartialResourceList.PartialDescriptors[0];
//
// Account for the space used by the controller.
//
partial->Type = CmResourceTypePort;
partial->ShareDisposition = CmResourceShareDeviceExclusive;
partial->Flags = (USHORT) 1;
partial->u.Port.Start = DeviceExtension->Configuration.PortAddress;
partial->u.Port.Length = DeviceExtension->Configuration.PortSize;
partial++;
if (DeviceExtension->Configuration.Interrupt.u.Interrupt.Vector) {
//
// Report the interrupt information.
//
partial->Type = CmResourceTypeInterrupt;
if (DeviceExtension->Configuration.Interrupt.ShareDisposition) {
partial->ShareDisposition = CmResourceShareShared;
} else {
partial->ShareDisposition = CmResourceShareDriverExclusive;
}
if (DeviceExtension->Configuration.Interrupt.Flags == Latched) {
partial->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
} else {
partial->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
}
partial->u.Interrupt.Vector =
DeviceExtension->Configuration.Interrupt.u.Interrupt.Vector;
partial->u.Interrupt.Level =
DeviceExtension->Configuration.Interrupt.u.Interrupt.Level;
countOfPartials++;
sizeOfResourceList += sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
}
resourceList->List[0].PartialResourceList.Count = countOfPartials;
RtlInitUnicodeString(&className,
L"PCMCIA Socket Resources");
#if 0
IoReportResourceUsage(&className,
DeviceExtension->DeviceObject->DriverObject,
NULL,
0,
DeviceExtension->DeviceObject,
resourceList,
sizeOfResourceList,
FALSE,
ConflictDetected);
#endif
ExFreePool(resourceList);
}
VOID
PcmciaUnReportResources(
IN PDEVICE_EXTENSION DeviceExtension
)
/*++
Routine Description:
Will delete resource usage from the system for this device.
Arguments:
DeviceExtension -- Pointer to the device extension
Returns Value:
none
--*/
{
CM_RESOURCE_LIST resourceList;
UNICODE_STRING className;
BOOLEAN tmp;
RtlZeroMemory(&resourceList, sizeof(CM_RESOURCE_LIST));
resourceList.Count = 0;
RtlInitUnicodeString(&className, L"PCMCIA SOCKET RESOURCES");
IoReportResourceUsage(&className,
DeviceExtension->DeviceObject->DriverObject,
NULL,
0,
DeviceExtension->DeviceObject,
&resourceList,
sizeof(CM_RESOURCE_LIST),
(BOOLEAN) FALSE,
&tmp);
}
NTSTATUS
PcmciaCheckDatabaseInformation(
PDEVICE_EXTENSION DeviceExtension,
PSOCKET Socket,
PSOCKET_DATA SocketData
)
/*++
Routine Description:
This routine goes into the PCMCIA database to find user provided
configuration parameters for the PCCARD - It also picks up
associations of tuple information (manufacturer name and device name)
to Windows NT driver. This allows for later construction of
configuration information in the volatile portion of the registry.
Arguments:
DeviceExtension - the base pointer for controller information
Socket - the socket involved
SocketData - specific information about the pccard in the socket
Return Value:
STATUS_SUCCESS if all works.
--*/
{
#ifdef ITEMS_TO_QUERY
#undef ITEMS_TO_QUERY
#endif
#define ITEMS_TO_QUERY 14
ULONG zero = 0;
ULONG nonzero = 1;
BOOLEAN haveOverride = FALSE;
UNICODE_STRING numberString;
WCHAR numberBuffer[8];
PSOCKET_CONFIGURATION override;
PRTL_QUERY_REGISTRY_TABLE socketParams;
NTSTATUS status;
UNICODE_STRING cardIdentU;
UNICODE_STRING cardMfgU;
PUNICODE_STRING registryPath;
UNICODE_STRING crcPath;
UNICODE_STRING socketPath;
UNICODE_STRING driverName;
OBJECT_ATTRIBUTES socketAttributes;
HANDLE socketKey;
ANSI_STRING cardIdentA;
ANSI_STRING cardMfgA;
ULONG configIndex;
ULONG interrupt;
ULONG port1;
ULONG port2;
ULONG ccrBase;
ULONG numPort1;
ULONG numPort2;
ULONG portWidth16;
ULONG cardMemorySize;
ULONG cardMemorySize1;
ULONG attrMemory;
ULONG attrMemory1;
registryPath = DeviceExtension->RegistryPath;
RtlInitAnsiString(&cardIdentA, &SocketData->Ident[0]);
RtlAnsiStringToUnicodeString(&cardIdentU, &cardIdentA, TRUE);
RtlInitAnsiString(&cardMfgA, &SocketData->Mfg[0]);
RtlAnsiStringToUnicodeString(&cardMfgU, &cardMfgA, TRUE);
//
// Open the registry key for socket A
//
RtlInitUnicodeString(&socketPath, NULL);
socketPath.MaximumLength = 4096;
socketPath.Buffer = ExAllocatePool(NonPagedPool, 4096);
if (!socketPath.Buffer) {
DebugPrint((PCMCIA_DEBUG_FAIL, "PCMCIA: Cannot allocate pool for key\n"));
RtlFreeUnicodeString(&cardIdentU);
RtlFreeUnicodeString(&cardMfgU);
return STATUS_NO_MEMORY;
}
//
// The registry key is registryPath\DataBase\<Mfg>\<Ident>
// See if it exists
//
RtlZeroMemory(socketPath.Buffer, socketPath.MaximumLength);
RtlAppendUnicodeStringToString(&socketPath, registryPath);
RtlAppendUnicodeToString(&socketPath, L"\\DataBase\\");
RtlAppendUnicodeToString(&socketPath, cardMfgU.Buffer);
RtlAppendUnicodeToString(&socketPath, L"\\");
RtlAppendUnicodeToString(&socketPath, cardIdentU.Buffer);
numberString.Buffer = numberBuffer;
numberString.MaximumLength = 8 * sizeof(WCHAR);
numberString.Length = 0;
RtlIntegerToUnicodeString(SocketData->CisCrc, 16, &numberString);
RtlInitUnicodeString(&crcPath, NULL);
crcPath.MaximumLength = 4096;
crcPath.Buffer = ExAllocatePool(NonPagedPool, 4096);
if (crcPath.Buffer) {
//
// Set up the CRC buffer name to see if there is a CRC
// specific key.
//
RtlZeroMemory(crcPath.Buffer, crcPath.MaximumLength);
RtlAppendUnicodeStringToString(&crcPath, &socketPath);
RtlAppendUnicodeToString(&crcPath, L"\\");
RtlAppendUnicodeStringToString(&crcPath, &numberString);
InitializeObjectAttributes(&socketAttributes,
&crcPath,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
if (NT_SUCCESS(status = ZwOpenKey(&socketKey,
MAXIMUM_ALLOWED,
&socketAttributes))) {
//
// The CRC key value is there - use it instead of the base key.
//
ZwClose(socketKey);
ExFreePool(socketPath.Buffer);
socketPath = crcPath;
} else {
//
// No key. Free allocated memory and continue on
// with base key name.
//
ExFreePool(crcPath.Buffer);
}
}
InitializeObjectAttributes(&socketAttributes,
&socketPath,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
if (!NT_SUCCESS(status = ZwOpenKey(&socketKey,
MAXIMUM_ALLOWED,
&socketAttributes))) {
//
// If this is of type ATA, then set the driver name
// to AtDisk.
//
if (SocketData->DeviceType == PCCARD_TYPE_ATA) {
driverName.Buffer = ExAllocatePool(NonPagedPool, 16);
if (driverName.Buffer) {
driverName.Length = 0;
driverName.MaximumLength = 16;
RtlAppendUnicodeToString(&driverName, L"AtDisk");
SocketData->DriverName = driverName;
status = STATUS_SUCCESS;
}
} else {
DebugPrint((PCMCIA_DEBUG_FAIL,
"PCMCIA: Could not open key %s\\%s (0x%x)\n",
cardMfgA.Buffer,
cardIdentA.Buffer,
status));
}
RtlFreeUnicodeString(&cardIdentU);
RtlFreeUnicodeString(&cardMfgU);
ExFreePool(socketPath.Buffer);
return status;
}
//
// The key exists - Query for driver name and override parameters
//
ZwClose(socketKey);
RtlFreeUnicodeString(&cardIdentU);
RtlFreeUnicodeString(&cardMfgU);
//
// Allocate the override structure;
//
override = ExAllocatePool(NonPagedPool, sizeof(SOCKET_CONFIGURATION));
if (!override) {
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlZeroMemory(override, sizeof(SOCKET_CONFIGURATION));
//
// Now look for the card name currently registered in the socket.
//
socketParams = ExAllocatePool(NonPagedPool,
sizeof(RTL_QUERY_REGISTRY_TABLE)*ITEMS_TO_QUERY);
if (!socketParams) {
ExFreePool(socketPath.Buffer);
ExFreePool(override);
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlZeroMemory(socketParams,
(sizeof(RTL_QUERY_REGISTRY_TABLE)*ITEMS_TO_QUERY));
socketParams[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
socketParams[0].Name = L"ConfiguredIndex";
socketParams[0].EntryContext = &configIndex;
socketParams[0].DefaultType = REG_DWORD;
socketParams[0].DefaultData = &zero;
socketParams[0].DefaultLength = sizeof(ULONG);
socketParams[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
socketParams[1].Name = L"InterruptNumber";
socketParams[1].EntryContext = &interrupt;
socketParams[1].DefaultType = REG_DWORD;
socketParams[1].DefaultData = &zero;
socketParams[1].DefaultLength = sizeof(ULONG);
socketParams[2].Flags = RTL_QUERY_REGISTRY_DIRECT;
socketParams[2].Name = L"IoBaseAddress";
socketParams[2].EntryContext = &port1;
socketParams[2].DefaultType = REG_DWORD;
socketParams[2].DefaultData = &zero;
socketParams[2].DefaultLength = sizeof(ULONG);
socketParams[3].Flags = RTL_QUERY_REGISTRY_DIRECT;
socketParams[3].Name = L"IoLength";
socketParams[3].EntryContext = &numPort1;
socketParams[3].DefaultType = REG_DWORD;
socketParams[3].DefaultData = &zero;
socketParams[3].DefaultLength = sizeof(ULONG);
socketParams[4].Flags = RTL_QUERY_REGISTRY_DIRECT;
socketParams[4].Name = L"IoBaseAddress_1";
socketParams[4].EntryContext = &port2;
socketParams[4].DefaultType = REG_DWORD;
socketParams[4].DefaultData = &zero;
socketParams[4].DefaultLength = sizeof(ULONG);
socketParams[5].Flags = RTL_QUERY_REGISTRY_DIRECT;
socketParams[5].Name = L"IoLength_1";
socketParams[5].EntryContext = &numPort2;
socketParams[5].DefaultType = REG_DWORD;
socketParams[5].DefaultData = &zero;
socketParams[5].DefaultLength = sizeof(ULONG);
socketParams[6].Flags = RTL_QUERY_REGISTRY_DIRECT;
socketParams[6].Name = L"CcrBase";
socketParams[6].EntryContext = &ccrBase;
socketParams[6].DefaultType = REG_DWORD;
socketParams[6].DefaultData = &zero;
socketParams[6].DefaultLength = sizeof(ULONG);
socketParams[7].Flags = RTL_QUERY_REGISTRY_DIRECT;
socketParams[7].Name = L"PortWidth16";
socketParams[7].EntryContext = &portWidth16;
socketParams[7].DefaultType = REG_DWORD;
socketParams[7].DefaultData = &zero;
socketParams[7].DefaultLength = sizeof(ULONG);
driverName.Buffer = NULL;
driverName.MaximumLength = driverName.Length = 0;
socketParams[8].Flags = RTL_QUERY_REGISTRY_DIRECT;
socketParams[8].Name = L"Driver";
socketParams[8].EntryContext = &driverName;
socketParams[8].DefaultType = REG_NONE;
socketParams[8].DefaultData = NULL;
socketParams[8].DefaultLength = 0;
socketParams[9].Flags = RTL_QUERY_REGISTRY_DIRECT;
socketParams[9].Name = L"CardMemorySize";
socketParams[9].EntryContext = &cardMemorySize;
socketParams[9].DefaultType = REG_DWORD;
socketParams[9].DefaultData = &nonzero;
socketParams[9].DefaultLength = sizeof(ULONG);
socketParams[10].Flags = RTL_QUERY_REGISTRY_DIRECT;
socketParams[10].Name = L"AttributeMemorySize";
socketParams[10].EntryContext = &attrMemory;
socketParams[10].DefaultType = REG_DWORD;
socketParams[10].DefaultData = &zero;
socketParams[10].DefaultLength = sizeof(ULONG);
socketParams[11].Flags = RTL_QUERY_REGISTRY_DIRECT;
socketParams[11].Name = L"CardMemorySize_1";
socketParams[11].EntryContext = &cardMemorySize1;
socketParams[11].DefaultType = REG_DWORD;
socketParams[11].DefaultData = &nonzero;
socketParams[11].DefaultLength = sizeof(ULONG);
socketParams[12].Flags = RTL_QUERY_REGISTRY_DIRECT;
socketParams[12].Name = L"AttributeMemorySize_1";
socketParams[12].EntryContext = &attrMemory1;
socketParams[12].DefaultType = REG_DWORD;
socketParams[12].DefaultData = &zero;
socketParams[12].DefaultLength = sizeof(ULONG);
status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
socketPath.Buffer,
socketParams,
NULL,
NULL);
//
// Save all of the override data for the PCCARD configuration
//
if (interrupt) {
override->Irq = interrupt;
haveOverride = TRUE;
}
if (port1 || port2) {
override->IoPortBase[0] = port1;
override->IoPortBase[1] = port2;
override->IoPortLength[0] = (USHORT) numPort1;
override->IoPortLength[1] = (USHORT) numPort2;
haveOverride = TRUE;
}
if (ccrBase) {
override->ConfigRegisterBase = (PUCHAR) ccrBase;
haveOverride = TRUE;
}
if (portWidth16) {
override->Uses16BitAccess = TRUE;
haveOverride = TRUE;
}
//
// Save the driver name
// - return an error if no driver name was located
//
if (driverName.Buffer) {
SocketData->DriverName = driverName;
} else {
status = STATUS_OBJECT_NAME_NOT_FOUND;
}
if (cardMemorySize != nonzero) {
SocketData->MemoryOverrideSize = cardMemorySize;
SocketData->HaveMemoryOverride = TRUE;
DebugPrint((PCMCIA_DEBUG_OVERRIDES,
"PCMCIA: override memory size 0 = %x\n",
cardMemorySize));
if (cardMemorySize1 != nonzero) {
SocketData->MemoryOverrideSize = cardMemorySize1;
DebugPrint((PCMCIA_DEBUG_OVERRIDES,
"PCMCIA: override memory size 1 = %x\n",
cardMemorySize1));
}
}
SocketData->AttributeMemorySize = attrMemory;
SocketData->AttributeMemorySize1 = attrMemory1;
if (attrMemory || attrMemory1) {
DebugPrint((PCMCIA_DEBUG_OVERRIDES,
"PCMCIA: attribute memory overrides %x - %x\n",
attrMemory,
attrMemory1));
}
if (haveOverride) {
SocketData->OverrideConfiguration = override;
} else {
ExFreePool(override);
}
ExFreePool(socketParams);
ExFreePool(socketPath.Buffer);
return status;
}
NTSTATUS
PcmciaCheckSerialRegistryInformation(
PDEVICE_EXTENSION DeviceExtension,
PSOCKET Socket,
PSOCKET_DATA SocketData,
PSOCKET_CONFIGURATION SocketConfig
)
/*++
Routine Description:
This routine goes into the serial registry key to see if any
user specified COM ports are assigned for PCMCIA
Arguments:
DeviceExtension - the base pointer for controller information
Socket - the socket involved
SocketData - specific information about the pccard in the socket
Return Value:
STATUS_SUCCESS if all works.
--*/
{
#ifdef ITEMS_TO_QUERY
#undef ITEMS_TO_QUERY
#endif
#define ITEMS_TO_QUERY 5
#define SUBKEY_EXTRA_LENGTH 256
ULONG zero = 0;
NTSTATUS status;
ULONG index;
ULONG bytesReturned;
ULONG pcmcia;
ULONG interrupt;
ULONG portAddress;
UNICODE_STRING unicodeName;
UNICODE_STRING subKeyName;
PRTL_QUERY_REGISTRY_TABLE socketParams;
PKEY_BASIC_INFORMATION subKeyInfo;
OBJECT_ATTRIBUTES attributes;
HANDLE handle;
//
// Determine if a search is necessary
//
if (DeviceExtension->SerialIndex == (USHORT) -1) {
return STATUS_OBJECT_NAME_NOT_FOUND;
}
//
// Construct the serial registry key name and open the key.
//
unicodeName.MaximumLength = 256 * sizeof(WCHAR);
unicodeName.Buffer = ExAllocatePool(NonPagedPool, unicodeName.MaximumLength);
if (!unicodeName.Buffer) {
return STATUS_INSUFFICIENT_RESOURCES;
}
unicodeName.Length = 0;
RtlAppendUnicodeToString(&unicodeName, L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services\\Serial\\Parameters");
InitializeObjectAttributes(&attributes,
&unicodeName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
status = ZwOpenKey(&handle,
MAXIMUM_ALLOWED,
&attributes);
if (!NT_SUCCESS(status)) {
ExFreePool(unicodeName.Buffer);
DeviceExtension->SerialIndex = (USHORT) -1;
return status;
}
//
// Set up to start the search
//
subKeyInfo = ExAllocatePool(NonPagedPool, sizeof(KEY_BASIC_INFORMATION) + (sizeof(WCHAR)*SUBKEY_EXTRA_LENGTH));
if (!subKeyInfo) {
ExFreePool(unicodeName.Buffer);
ZwClose(handle);
return STATUS_INSUFFICIENT_RESOURCES;
}
index = (ULONG) DeviceExtension->SerialIndex;
socketParams = ExAllocatePool(NonPagedPool,
sizeof(RTL_QUERY_REGISTRY_TABLE)*ITEMS_TO_QUERY);
if (!socketParams) {
ExFreePool(unicodeName.Buffer);
ExFreePool(subKeyInfo);
ZwClose(handle);
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// Construct the query shell.
//
RtlZeroMemory(socketParams, (sizeof(RTL_QUERY_REGISTRY_TABLE)*ITEMS_TO_QUERY));
socketParams[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
socketParams[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
socketParams[1].Name = L"Interrupt";
socketParams[1].EntryContext = &interrupt;
socketParams[1].DefaultType = REG_DWORD;
socketParams[1].DefaultData = &zero;
socketParams[1].DefaultLength = sizeof(ULONG);
socketParams[2].Flags = RTL_QUERY_REGISTRY_DIRECT;
socketParams[2].Name = L"PortAddress";
socketParams[2].EntryContext = &portAddress;
socketParams[2].DefaultType = REG_DWORD;
socketParams[2].DefaultData = &zero;
socketParams[2].DefaultLength = sizeof(ULONG);
socketParams[3].Flags = RTL_QUERY_REGISTRY_DIRECT;
socketParams[3].Name = L"Pcmcia";
socketParams[3].EntryContext = &pcmcia;
socketParams[3].DefaultType = REG_DWORD;
socketParams[3].DefaultData = &zero;
socketParams[3].DefaultLength = sizeof(ULONG);
while (TRUE) {
//
// Find the index entry in the registry.
//
RtlZeroMemory(subKeyInfo, sizeof(KEY_BASIC_INFORMATION)+(sizeof(WCHAR)*SUBKEY_EXTRA_LENGTH));
status = ZwEnumerateKey(handle,
index,
KeyBasicInformation,
subKeyInfo,
sizeof(KEY_BASIC_INFORMATION)+(sizeof(WCHAR)*(SUBKEY_EXTRA_LENGTH - 1)),
&bytesReturned);
if (status == STATUS_NO_MORE_ENTRIES) {
status = STATUS_OBJECT_NAME_NOT_FOUND;
DeviceExtension->SerialIndex = (USHORT) -1;
break;
}
index++;
if (!NT_SUCCESS(status)) {
//
// This could be a buffer overflow or some permissions thing.
// Just skip this entry.
//
continue;
}
//
// e-o-s the subkey name for the registry query.
//
RtlZeroMemory(((PUCHAR)(&subKeyInfo->Name[0])) + subKeyInfo->NameLength, sizeof(WCHAR));
socketParams[0].Name = &subKeyInfo->Name[0];
//
// Now look for the card name currently registered in the socket.
//
portAddress = interrupt = pcmcia = 0;
status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
unicodeName.Buffer,
socketParams,
NULL,
NULL);
if (NT_SUCCESS(status)) {
if (pcmcia) {
//
// Save away the user requested configuration for this modem.
//
SocketConfig->IoPortBase[0] = portAddress;
SocketConfig->Irq = interrupt;
DeviceExtension->SerialIndex = (USHORT) index;
break;
}
}
}
ExFreePool(socketParams);
ExFreePool(unicodeName.Buffer);
ZwClose(handle);
return status;
}
NTSTATUS
PcmciaCheckNetworkRegistryInformation(
PDEVICE_EXTENSION DeviceExtension,
PSOCKET Socket,
PSOCKET_DATA SocketData,
PSOCKET_CONFIGURATION SocketConfiguration
)
/*++
Routine Description:
This routine goes into the network portion of the registry to
see if a configuration has been specified for the PCCARD.
Arguments:
DeviceExtension - the base pointer for controller information
Socket - the socket involved
SocketData - specific information about the pccard in the socket
Return Value:
STATUS_SUCCESS if all works.
--*/
{
#ifdef ITEMS_TO_QUERY
#undef ITEMS_TO_QUERY
#endif
#define ITEMS_TO_QUERY 33
ULONG zero = 0;
PRTL_QUERY_REGISTRY_TABLE socketParams;
NTSTATUS status;
UNICODE_STRING socketPath;
UNICODE_STRING driverName;
UNICODE_STRING numberString;
WCHAR numberBuffer[4];
OBJECT_ATTRIBUTES socketAttributes;
HANDLE socketKey;
ANSI_STRING cardIdentA;
ANSI_STRING cardMfgA;
ULONG configIndex;
ULONG interrupt;
ULONG port;
ULONG portLength;
ULONG port_1;
ULONG portLength_1;
ULONG memory;
ULONG cardMemoryOffset;
ULONG cardMemorySize;
ULONG memory_1;
ULONG cardMemoryOffset_1;
ULONG cardMemorySize_1;
ULONG memory_2;
ULONG cardMemoryOffset_2;
ULONG cardMemorySize_2;
ULONG memory_3;
ULONG cardMemoryOffset_3;
ULONG cardMemorySize_3;
ULONG attributeMemory;
ULONG attributeMemoryLength;
ULONG attributeMemoryOffset;
ULONG attributeMemory1;
ULONG attributeMemoryLength1;
ULONG attributeMemoryOffset1;
ULONG readyInterrupt;
ULONG address_16;
ULONG address1_16;
ULONG address2_16;
ULONG address3_16;
ULONG attributeMemory_16;
ULONG attributeMemory1_16;
ULONG pcmcia;
ULONG multiFunction;
driverName = SocketData->DriverName;
if (!driverName.Buffer) {
return STATUS_UNSUCCESSFUL;
}
//
// Allocate memory to maintain name for registry key
//
RtlInitUnicodeString(&socketPath, NULL);
socketPath.MaximumLength = 4096;
socketPath.Buffer = ExAllocatePool(NonPagedPool, 4096);
if (!socketPath.Buffer) {
DebugPrint((PCMCIA_DEBUG_FAIL, "PCMCIA: Cannot allocate pool for net key\n"));
return STATUS_NO_MEMORY;
}
//
// Allocate registry query structure.
//
socketParams = ExAllocatePool(NonPagedPool,
sizeof(RTL_QUERY_REGISTRY_TABLE)*ITEMS_TO_QUERY);
if (!socketParams) {
ExFreePool(socketPath.Buffer);
return STATUS_INSUFFICIENT_RESOURCES;
}
numberString.Buffer = numberBuffer;
numberString.MaximumLength = 4 * sizeof(WCHAR);
numberString.Length = 0;
for (configIndex = 1; configIndex < 10; configIndex++) {
//
// Construct the unicode string for this index.
//
RtlIntegerToUnicodeString(configIndex, 10, &numberString);
//
// The registry key is SYSTEM\CurrentControlSet\Services\<driver>#\Parameters
//
RtlZeroMemory(socketPath.Buffer, socketPath.MaximumLength);
socketPath.Length = 0;
RtlAppendUnicodeToString(&socketPath, L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services\\");
RtlAppendUnicodeToString(&socketPath, driverName.Buffer);
RtlAppendUnicodeToString(&socketPath, numberString.Buffer);
RtlAppendUnicodeToString(&socketPath, L"\\Parameters");
InitializeObjectAttributes(&socketAttributes,
&socketPath,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
if (!NT_SUCCESS(status = ZwOpenKey(&socketKey,
MAXIMUM_ALLOWED,
&socketAttributes))) {
//
// Keep searching.
//
continue;
}
//
// The key exists - Query for configuration
//
ZwClose(socketKey);
RtlZeroMemory(socketParams,
sizeof(RTL_QUERY_REGISTRY_TABLE)*ITEMS_TO_QUERY);
socketParams[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
socketParams[0].Name = L"InterruptNumber";
socketParams[0].EntryContext = &interrupt;
socketParams[0].DefaultType = REG_DWORD;
socketParams[0].DefaultData = &zero;
socketParams[0].DefaultLength = sizeof(ULONG);
socketParams[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
socketParams[1].Name = L"IoBaseAddress";
socketParams[1].EntryContext = &port;
socketParams[1].DefaultType = REG_DWORD;
socketParams[1].DefaultData = &zero;
socketParams[1].DefaultLength = sizeof(ULONG);
socketParams[2].Flags = RTL_QUERY_REGISTRY_DIRECT;
socketParams[2].Name = L"IoLength";
socketParams[2].EntryContext = &portLength;
socketParams[2].DefaultType = REG_DWORD;
socketParams[2].DefaultData = &zero;
socketParams[2].DefaultLength = sizeof(ULONG);
socketParams[3].Flags = RTL_QUERY_REGISTRY_DIRECT;
socketParams[3].Name = L"IoBaseAddress_1";
socketParams[3].EntryContext = &port_1;
socketParams[3].DefaultType = REG_DWORD;
socketParams[3].DefaultData = &zero;
socketParams[3].DefaultLength = sizeof(ULONG);
socketParams[4].Flags = RTL_QUERY_REGISTRY_DIRECT;
socketParams[4].Name = L"IoLength_1";
socketParams[4].EntryContext = &portLength_1;
socketParams[4].DefaultType = REG_DWORD;
socketParams[4].DefaultData = &zero;
socketParams[4].DefaultLength = sizeof(ULONG);
socketParams[5].Flags = RTL_QUERY_REGISTRY_DIRECT;
socketParams[5].Name = L"MemoryMappedBaseAddress";
socketParams[5].EntryContext = &memory;
socketParams[5].DefaultType = REG_DWORD;
socketParams[5].DefaultData = &zero;
socketParams[5].DefaultLength = sizeof(ULONG);
socketParams[6].Flags = RTL_QUERY_REGISTRY_DIRECT;
socketParams[6].Name = L"MemoryMappedSize";
socketParams[6].EntryContext = &cardMemorySize;
socketParams[6].DefaultType = REG_DWORD;
socketParams[6].DefaultData = &zero;
socketParams[6].DefaultLength = sizeof(ULONG);
socketParams[7].Flags = RTL_QUERY_REGISTRY_DIRECT;
socketParams[7].Name = L"PCCARDMemoryWindowOffset";
socketParams[7].EntryContext = &cardMemoryOffset;
socketParams[7].DefaultType = REG_DWORD;
socketParams[7].DefaultData = &zero;
socketParams[7].DefaultLength = sizeof(ULONG);
socketParams[8].Flags = RTL_QUERY_REGISTRY_DIRECT;
socketParams[8].Name = L"MemoryMappedBaseAddress_1";
socketParams[8].EntryContext = &memory_1;
socketParams[8].DefaultType = REG_DWORD;
socketParams[8].DefaultData = &zero;
socketParams[8].DefaultLength = sizeof(ULONG);
socketParams[9].Flags = RTL_QUERY_REGISTRY_DIRECT;
socketParams[9].Name = L"MemoryMappedSize_1";
socketParams[9].EntryContext = &cardMemorySize_1;
socketParams[9].DefaultType = REG_DWORD;
socketParams[9].DefaultData = &zero;
socketParams[9].DefaultLength = sizeof(ULONG);
socketParams[10].Flags = RTL_QUERY_REGISTRY_DIRECT;
socketParams[10].Name = L"PCCARDMemoryWindowOffset_1";
socketParams[10].EntryContext = &cardMemoryOffset_1;
socketParams[10].DefaultType = REG_DWORD;
socketParams[10].DefaultData = &zero;
socketParams[10].DefaultLength = sizeof(ULONG);
socketParams[11].Flags = RTL_QUERY_REGISTRY_DIRECT;
socketParams[11].Name = L"Pcmcia";
socketParams[11].EntryContext = &pcmcia;
socketParams[11].DefaultType = REG_DWORD;
socketParams[11].DefaultData = &zero;
socketParams[11].DefaultLength = sizeof(ULONG);
socketParams[12].Flags = RTL_QUERY_REGISTRY_DIRECT;
socketParams[12].Name = L"PCCARDAttributeMemoryAddress";
socketParams[12].EntryContext = &attributeMemory;
socketParams[12].DefaultType = REG_DWORD;
socketParams[12].DefaultData = &zero;
socketParams[12].DefaultLength = sizeof(ULONG);
socketParams[13].Flags = RTL_QUERY_REGISTRY_DIRECT;
socketParams[13].Name = L"PCCARDAttributeMemorySize";
socketParams[13].EntryContext = &attributeMemoryLength;
socketParams[13].DefaultType = REG_DWORD;
socketParams[13].DefaultData = &zero;
socketParams[13].DefaultLength = sizeof(ULONG);
socketParams[14].Flags = RTL_QUERY_REGISTRY_DIRECT;
socketParams[14].Name = L"PCCARDAttributeMemoryOffset";
socketParams[14].EntryContext = &attributeMemoryOffset;
socketParams[14].DefaultType = REG_DWORD;
socketParams[14].DefaultData = &zero;
socketParams[14].DefaultLength = sizeof(ULONG);
//
// Allow for service to monitor card removal if desired.
//
socketParams[15].Flags = RTL_QUERY_REGISTRY_DIRECT;
socketParams[15].Name = L"PCCARDReadyInterrupt";
socketParams[15].EntryContext = &readyInterrupt;
socketParams[15].DefaultType = REG_DWORD;
socketParams[15].DefaultData = &zero;
socketParams[15].DefaultLength = sizeof(ULONG);
socketParams[16].Flags = RTL_QUERY_REGISTRY_DIRECT;
socketParams[16].Name = L"MemoryMappedBaseAddress_2";
socketParams[16].EntryContext = &memory_2;
socketParams[16].DefaultType = REG_DWORD;
socketParams[16].DefaultData = &zero;
socketParams[16].DefaultLength = sizeof(ULONG);
socketParams[17].Flags = RTL_QUERY_REGISTRY_DIRECT;
socketParams[17].Name = L"MemoryMappedSize_2";
socketParams[17].EntryContext = &cardMemorySize_2;
socketParams[17].DefaultType = REG_DWORD;
socketParams[17].DefaultData = &zero;
socketParams[17].DefaultLength = sizeof(ULONG);
socketParams[18].Flags = RTL_QUERY_REGISTRY_DIRECT;
socketParams[18].Name = L"PCCARDMemoryWindowOffset_2";
socketParams[18].EntryContext = &cardMemoryOffset_2;
socketParams[18].DefaultType = REG_DWORD;
socketParams[18].DefaultData = &zero;
socketParams[18].DefaultLength = sizeof(ULONG);
socketParams[19].Flags = RTL_QUERY_REGISTRY_DIRECT;
socketParams[19].Name = L"MemoryMappedBaseAddress_3";
socketParams[19].EntryContext = &memory_3;
socketParams[19].DefaultType = REG_DWORD;
socketParams[19].DefaultData = &zero;
socketParams[19].DefaultLength = sizeof(ULONG);
socketParams[20].Flags = RTL_QUERY_REGISTRY_DIRECT;
socketParams[20].Name = L"MemoryMappedSize_3";
socketParams[20].EntryContext = &cardMemorySize_3;
socketParams[20].DefaultType = REG_DWORD;
socketParams[20].DefaultData = &zero;
socketParams[20].DefaultLength = sizeof(ULONG);
socketParams[21].Flags = RTL_QUERY_REGISTRY_DIRECT;
socketParams[21].Name = L"PCCARDMemoryWindowOffset_3";
socketParams[21].EntryContext = &cardMemoryOffset_3;
socketParams[21].DefaultType = REG_DWORD;
socketParams[21].DefaultData = &zero;
socketParams[21].DefaultLength = sizeof(ULONG);
socketParams[22].Flags = RTL_QUERY_REGISTRY_DIRECT;
socketParams[22].Name = L"PCCARDAttributeMemoryAddress_1";
socketParams[22].EntryContext = &attributeMemory1;
socketParams[22].DefaultType = REG_DWORD;
socketParams[22].DefaultData = &zero;
socketParams[22].DefaultLength = sizeof(ULONG);
socketParams[23].Flags = RTL_QUERY_REGISTRY_DIRECT;
socketParams[23].Name = L"PCCARDAttributeMemorySize_1";
socketParams[23].EntryContext = &attributeMemoryLength1;
socketParams[23].DefaultType = REG_DWORD;
socketParams[23].DefaultData = &zero;
socketParams[23].DefaultLength = sizeof(ULONG);
socketParams[24].Flags = RTL_QUERY_REGISTRY_DIRECT;
socketParams[24].Name = L"PCCARDAttributeMemoryOffset_1";
socketParams[24].EntryContext = &attributeMemoryOffset1;
socketParams[24].DefaultType = REG_DWORD;
socketParams[24].DefaultData = &zero;
socketParams[24].DefaultLength = sizeof(ULONG);
//
// Set up to get the memory access attribute parameters
//
socketParams[25].Flags = RTL_QUERY_REGISTRY_DIRECT;
socketParams[25].Name = L"Address_16";
socketParams[25].EntryContext = &address_16;
socketParams[25].DefaultType = REG_DWORD;
socketParams[25].DefaultData = &zero;
socketParams[25].DefaultLength = sizeof(ULONG);
socketParams[26].Flags = RTL_QUERY_REGISTRY_DIRECT;
socketParams[26].Name = L"Address1_16";
socketParams[26].EntryContext = &address1_16;
socketParams[26].DefaultType = REG_DWORD;
socketParams[26].DefaultData = &zero;
socketParams[26].DefaultLength = sizeof(ULONG);
socketParams[27].Flags = RTL_QUERY_REGISTRY_DIRECT;
socketParams[27].Name = L"Address2_16";
socketParams[27].EntryContext = &address2_16;
socketParams[27].DefaultType = REG_DWORD;
socketParams[27].DefaultData = &zero;
socketParams[27].DefaultLength = sizeof(ULONG);
socketParams[28].Flags = RTL_QUERY_REGISTRY_DIRECT;
socketParams[28].Name = L"Address3_16";
socketParams[28].EntryContext = &address3_16;
socketParams[28].DefaultType = REG_DWORD;
socketParams[28].DefaultData = &zero;
socketParams[28].DefaultLength = sizeof(ULONG);
socketParams[29].Flags = RTL_QUERY_REGISTRY_DIRECT;
socketParams[29].Name = L"AttributeMemory_16";
socketParams[29].EntryContext = &attributeMemory_16;
socketParams[29].DefaultType = REG_DWORD;
socketParams[29].DefaultData = &zero;
socketParams[29].DefaultLength = sizeof(ULONG);
socketParams[30].Flags = RTL_QUERY_REGISTRY_DIRECT;
socketParams[30].Name = L"AttributeMemory1_16";
socketParams[30].EntryContext = &attributeMemory1_16;
socketParams[30].DefaultType = REG_DWORD;
socketParams[30].DefaultData = &zero;
socketParams[30].DefaultLength = sizeof(ULONG);
socketParams[31].Flags = RTL_QUERY_REGISTRY_DIRECT;
socketParams[31].Name = L"ModemFunction";
socketParams[31].EntryContext = &multiFunction;
socketParams[31].DefaultType = REG_DWORD;
socketParams[31].DefaultData = &zero;
socketParams[31].DefaultLength = sizeof(ULONG);
//
// Make registry query
//
status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
socketPath.Buffer,
socketParams,
NULL,
NULL);
if (NT_SUCCESS(status)) {
//
// see if this configuration is for PCMCIA
//
if (pcmcia) {
ULONG index = 0;
//
// Save all of the PCCARD configuration
// must have a port or interrupt to be considered valid.
//
if (port || interrupt) {
SocketConfiguration->IoPortBase[0] = port;
SocketConfiguration->IoPortLength[0] = (USHORT)portLength;
SocketConfiguration->IoPortBase[1] = port_1;
SocketConfiguration->IoPortLength[1] = (USHORT)portLength_1;
SocketConfiguration->Irq = interrupt;
SocketConfiguration->ReadyIrq = readyInterrupt;
if (attributeMemory) {
SocketConfiguration->MemoryHostBase[0] = attributeMemory;
SocketConfiguration->MemoryCardBase[0] = attributeMemoryOffset;
SocketConfiguration->MemoryLength[0] = attributeMemoryLength - 1;
SocketConfiguration->IsAttributeMemory[0] = 1;
index++;
} else {
if (SocketData->AttributeMemorySize) {
//
// This card needs an attribute memory window
// at any convienient location.
//
SocketConfiguration->MemoryHostBase[0] = DeviceExtension->PhysicalBase + 0x4000;
SocketConfiguration->MemoryCardBase[0] = 0;
SocketConfiguration->MemoryLength[0] = SocketData->AttributeMemorySize - 1;
SocketConfiguration->IsAttributeMemory[0] = 1;
SocketConfiguration->Is16BitAccessToMemory[0] = (UCHAR) attributeMemory_16;
index++;
}
}
if (attributeMemory1) {
SocketConfiguration->MemoryHostBase[index] = attributeMemory1;
SocketConfiguration->MemoryCardBase[index] = attributeMemoryOffset1;
SocketConfiguration->MemoryLength[index] = attributeMemoryLength1 - 1;
SocketConfiguration->IsAttributeMemory[index] = 1;
SocketConfiguration->Is16BitAccessToMemory[index] = (UCHAR) attributeMemory1_16;
index++;
}
if (memory) {
SocketConfiguration->MemoryHostBase[index] = memory;
SocketConfiguration->MemoryCardBase[index] = cardMemoryOffset;
SocketConfiguration->MemoryLength[index] = cardMemorySize - 1;
SocketConfiguration->Is16BitAccessToMemory[index] = (UCHAR) address_16;
index++;
}
if (memory_1) {
SocketConfiguration->MemoryHostBase[index] = memory_1;
SocketConfiguration->MemoryCardBase[index] = cardMemoryOffset_1;
SocketConfiguration->MemoryLength[index] = cardMemorySize_1 - 1;
SocketConfiguration->Is16BitAccessToMemory[index] = (UCHAR) address1_16;
index++;
}
if (index < MAX_NUMBER_OF_MEMORY_RANGES) {
if (memory_2) {
SocketConfiguration->MemoryHostBase[index] = memory_2;
SocketConfiguration->MemoryCardBase[index] = cardMemoryOffset_2;
SocketConfiguration->MemoryLength[index] = cardMemorySize_2 - 1;
SocketConfiguration->Is16BitAccessToMemory[index] = (UCHAR) address2_16;
index++;
}
if (index < MAX_NUMBER_OF_MEMORY_RANGES) {
if (memory_3) {
SocketConfiguration->MemoryHostBase[index] = memory_3;
SocketConfiguration->MemoryCardBase[index] = cardMemoryOffset_3;
SocketConfiguration->MemoryLength[index] = cardMemorySize_3 - 1;
SocketConfiguration->Is16BitAccessToMemory[index] = (UCHAR) address3_16;
index++;
}
}
}
SocketConfiguration->NumberOfMemoryRanges = index;
for (index = 0; index < SocketConfiguration->NumberOfMemoryRanges; index++) {
DebugPrint((PCMCIA_DEBUG_ENABLE, "PCMCIA network registry: memory=%x card=%x length=%x %s\n",
SocketConfiguration->MemoryHostBase[index],
SocketConfiguration->MemoryCardBase[index],
SocketConfiguration->MemoryLength[index],
SocketConfiguration->IsAttributeMemory[index] ? "AttributeMemory" : ""));
}
SocketConfiguration->MultiFunctionModem = multiFunction;
} else {
status = STATUS_UNSUCCESSFUL;
}
break;
} else {
status = STATUS_UNSUCCESSFUL;
}
}
}
if (socketParams) {
ExFreePool(socketParams);
}
ExFreePool(socketPath.Buffer);
return status;
}
VOID
PcmciaRegistryMemoryWindow(
PDEVICE_EXTENSION DeviceExtension
)
/*++
Routine Description:
Search the registry to find if the user has selected a memory window
to be used instead of the default for attibute memory.
Arguments:
DeviceExtension - where to save the values if they are present
Return Value:
Non-zero - new physical base for attempting to find memory window
zero - no base provided - use defaults.
--*/
{
#ifdef ITEMS_TO_QUERY
#undef ITEMS_TO_QUERY
#endif
#define ITEMS_TO_QUERY 3
ULONG zero = 0;
ULONG memoryWindow;
ULONG interruptMask;
PRTL_QUERY_REGISTRY_TABLE parms;
NTSTATUS status;
//
// Setup the query for memory window.
//
parms = ExAllocatePool(NonPagedPool,
sizeof(RTL_QUERY_REGISTRY_TABLE)*ITEMS_TO_QUERY);
if (!parms) {
DebugPrint((PCMCIA_DEBUG_FAIL, "PCMCIA: no memory for window query\n"));
return;
}
RtlZeroMemory(parms,
(sizeof(RTL_QUERY_REGISTRY_TABLE)*ITEMS_TO_QUERY));
parms[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
parms[0].Name = L"MemoryWindow";
parms[0].EntryContext = &memoryWindow;
parms[0].DefaultType = REG_DWORD;
parms[0].DefaultData = &zero;
parms[0].DefaultLength = sizeof(ULONG);
parms[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
parms[1].Name = L"InterruptMask";
parms[1].EntryContext = &interruptMask;
parms[1].DefaultType = REG_DWORD;
parms[1].DefaultData = &zero;
parms[1].DefaultLength = sizeof(ULONG);
//
// Perform the query
//
status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
DeviceExtension->RegistryPath->Buffer,
parms,
NULL,
NULL);
ExFreePool(parms);
if (memoryWindow) {
DeviceExtension->PhysicalBase = memoryWindow;
}
if (interruptMask) {
DebugPrint((PCMCIA_DEBUG_IRQMASK,
"PCMCIA: Registry provided IRQ mask %x\n",
interruptMask));
DeviceExtension->AllocatedIrqlMask = interruptMask;
}
}