2487 lines
83 KiB
C
2487 lines
83 KiB
C
|
|
|||
|
/*++
|
|||
|
|
|||
|
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;
|
|||
|
}
|
|||
|
}
|