2010-04-07 20:19:29 +00:00
|
|
|
/*
|
|
|
|
* PROJECT: ReactOS ISA PnP Bus driver
|
|
|
|
* FILE: pdo.c
|
|
|
|
* PURPOSE: PDO-specific code
|
|
|
|
* PROGRAMMERS: Cameron Gutman (cameron.gutman@reactos.org)
|
|
|
|
*/
|
2014-02-06 11:18:34 +00:00
|
|
|
|
2010-04-07 20:19:29 +00:00
|
|
|
#include <isapnp.h>
|
2020-03-16 19:50:29 +00:00
|
|
|
#include <isapnphw.h>
|
2010-04-07 20:19:29 +00:00
|
|
|
|
|
|
|
#define NDEBUG
|
|
|
|
#include <debug.h>
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
IsaPdoQueryDeviceRelations(
|
2020-03-20 18:19:30 +00:00
|
|
|
IN PISAPNP_PDO_EXTENSION PdoExt,
|
|
|
|
IN PIRP Irp,
|
|
|
|
IN PIO_STACK_LOCATION IrpSp)
|
2010-04-07 20:19:29 +00:00
|
|
|
{
|
2020-03-20 18:19:30 +00:00
|
|
|
PDEVICE_RELATIONS DeviceRelations;
|
2010-04-07 20:19:29 +00:00
|
|
|
|
2020-03-16 18:43:37 +00:00
|
|
|
if (IrpSp->Parameters.QueryDeviceRelations.Type == RemovalRelations &&
|
|
|
|
PdoExt->Common.Self == PdoExt->FdoExt->DataPortPdo)
|
|
|
|
{
|
|
|
|
return IsaPnpFillDeviceRelations(PdoExt->FdoExt, Irp, FALSE);
|
|
|
|
}
|
|
|
|
|
2020-03-20 18:19:30 +00:00
|
|
|
if (IrpSp->Parameters.QueryDeviceRelations.Type != TargetDeviceRelation)
|
|
|
|
return Irp->IoStatus.Status;
|
2010-04-07 20:19:29 +00:00
|
|
|
|
2020-03-20 18:19:30 +00:00
|
|
|
DeviceRelations = ExAllocatePool(PagedPool, sizeof(*DeviceRelations));
|
|
|
|
if (!DeviceRelations)
|
2020-03-20 18:41:55 +00:00
|
|
|
return STATUS_NO_MEMORY;
|
2010-04-07 20:19:29 +00:00
|
|
|
|
2020-03-20 18:19:30 +00:00
|
|
|
DeviceRelations->Count = 1;
|
|
|
|
DeviceRelations->Objects[0] = PdoExt->Common.Self;
|
|
|
|
ObReferenceObject(PdoExt->Common.Self);
|
2010-04-07 20:19:29 +00:00
|
|
|
|
2020-03-20 18:19:30 +00:00
|
|
|
Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
|
2010-04-07 20:19:29 +00:00
|
|
|
|
2020-03-20 18:19:30 +00:00
|
|
|
return STATUS_SUCCESS;
|
2010-04-07 20:19:29 +00:00
|
|
|
}
|
|
|
|
|
2020-02-10 20:31:28 +00:00
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
IsaPdoQueryCapabilities(
|
2020-03-20 18:19:30 +00:00
|
|
|
IN PISAPNP_PDO_EXTENSION PdoExt,
|
|
|
|
IN PIRP Irp,
|
|
|
|
IN PIO_STACK_LOCATION IrpSp)
|
2020-02-10 20:31:28 +00:00
|
|
|
{
|
2020-03-20 18:19:30 +00:00
|
|
|
PDEVICE_CAPABILITIES DeviceCapabilities;
|
|
|
|
PISAPNP_LOGICAL_DEVICE LogDev = PdoExt->IsaPnpDevice;
|
2020-03-16 18:24:07 +00:00
|
|
|
ULONG i;
|
2020-02-10 20:31:28 +00:00
|
|
|
|
2020-03-20 18:19:30 +00:00
|
|
|
DeviceCapabilities = IrpSp->Parameters.DeviceCapabilities.Capabilities;
|
|
|
|
if (DeviceCapabilities->Version != 1)
|
2020-03-20 18:41:55 +00:00
|
|
|
return STATUS_REVISION_MISMATCH;
|
2020-02-10 20:31:28 +00:00
|
|
|
|
2020-03-16 18:24:07 +00:00
|
|
|
if (LogDev)
|
|
|
|
{
|
|
|
|
DeviceCapabilities->UniqueID = LogDev->SerialNumber != 0xffffffff;
|
|
|
|
DeviceCapabilities->Address = LogDev->CSN;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DeviceCapabilities->UniqueID = TRUE;
|
|
|
|
DeviceCapabilities->SilentInstall = TRUE;
|
|
|
|
DeviceCapabilities->RawDeviceOK = TRUE;
|
|
|
|
for (i = 0; i < POWER_SYSTEM_MAXIMUM; i++)
|
|
|
|
DeviceCapabilities->DeviceState[i] = PowerDeviceD3;
|
|
|
|
DeviceCapabilities->DeviceState[PowerSystemWorking] = PowerDeviceD0;
|
|
|
|
}
|
2020-02-10 20:31:28 +00:00
|
|
|
|
2020-03-20 18:19:30 +00:00
|
|
|
return STATUS_SUCCESS;
|
2020-02-10 20:31:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
IsaPdoQueryId(
|
2020-03-20 18:19:30 +00:00
|
|
|
IN PISAPNP_PDO_EXTENSION PdoExt,
|
|
|
|
IN PIRP Irp,
|
|
|
|
IN PIO_STACK_LOCATION IrpSp)
|
2020-02-10 20:31:28 +00:00
|
|
|
{
|
2020-03-16 18:00:00 +00:00
|
|
|
UNICODE_STRING EmptyString = RTL_CONSTANT_STRING(L"");
|
|
|
|
PUNICODE_STRING Source;
|
|
|
|
PWCHAR Buffer;
|
2020-03-20 18:19:30 +00:00
|
|
|
|
|
|
|
switch (IrpSp->Parameters.QueryId.IdType)
|
2020-02-10 20:31:28 +00:00
|
|
|
{
|
2020-03-20 18:19:30 +00:00
|
|
|
case BusQueryDeviceID:
|
|
|
|
DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryDeviceID\n");
|
2020-03-16 18:00:00 +00:00
|
|
|
Source = &PdoExt->DeviceID;
|
2020-03-20 18:19:30 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case BusQueryHardwareIDs:
|
|
|
|
DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryHardwareIDs\n");
|
2020-03-16 18:00:00 +00:00
|
|
|
Source = &PdoExt->HardwareIDs;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case BusQueryCompatibleIDs:
|
|
|
|
DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryCompatibleIDs\n");
|
|
|
|
Source = &EmptyString;
|
2020-03-20 18:19:30 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case BusQueryInstanceID:
|
|
|
|
DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryInstanceID\n");
|
2020-03-16 18:00:00 +00:00
|
|
|
Source = &PdoExt->InstanceID;
|
2020-03-20 18:19:30 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2020-03-16 18:00:00 +00:00
|
|
|
DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_ID / unknown query id type 0x%lx\n",
|
|
|
|
IrpSp->Parameters.QueryId.IdType);
|
|
|
|
return Irp->IoStatus.Status;
|
2020-02-10 20:31:28 +00:00
|
|
|
}
|
|
|
|
|
2020-03-16 18:00:00 +00:00
|
|
|
Buffer = ExAllocatePool(PagedPool, Source->MaximumLength);
|
2020-03-20 18:19:30 +00:00
|
|
|
if (!Buffer)
|
|
|
|
return STATUS_NO_MEMORY;
|
|
|
|
|
2020-03-16 18:00:00 +00:00
|
|
|
RtlCopyMemory(Buffer, Source->Buffer, Source->MaximumLength);
|
2020-03-20 18:19:30 +00:00
|
|
|
Irp->IoStatus.Information = (ULONG_PTR)Buffer;
|
|
|
|
return STATUS_SUCCESS;
|
2020-02-10 20:31:28 +00:00
|
|
|
}
|
|
|
|
|
2020-03-16 19:50:29 +00:00
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
IsaPdoQueryResources(
|
|
|
|
IN PISAPNP_PDO_EXTENSION PdoExt,
|
|
|
|
IN PIRP Irp,
|
|
|
|
IN PIO_STACK_LOCATION IrpSp)
|
|
|
|
{
|
|
|
|
USHORT Ports[] = { ISAPNP_WRITE_DATA, ISAPNP_ADDRESS };
|
|
|
|
ULONG ListSize, i;
|
|
|
|
PCM_RESOURCE_LIST ResourceList;
|
|
|
|
PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
|
|
|
|
|
|
|
|
ListSize = sizeof(CM_RESOURCE_LIST)
|
|
|
|
+ (ARRAYSIZE(Ports) - 1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
|
|
|
|
ResourceList = ExAllocatePool(NonPagedPool, ListSize);
|
|
|
|
if (!ResourceList)
|
|
|
|
return STATUS_NO_MEMORY;
|
|
|
|
|
|
|
|
RtlZeroMemory(ResourceList, ListSize);
|
|
|
|
ResourceList->Count = 1;
|
|
|
|
ResourceList->List[0].InterfaceType = Internal;
|
|
|
|
ResourceList->List[0].PartialResourceList.Version = 1;
|
|
|
|
ResourceList->List[0].PartialResourceList.Revision = 1;
|
|
|
|
ResourceList->List[0].PartialResourceList.Count = 2;
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAYSIZE(Ports); i++)
|
|
|
|
{
|
|
|
|
Descriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[i];
|
|
|
|
Descriptor->Type = CmResourceTypePort;
|
|
|
|
Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
|
|
|
|
Descriptor->Flags = CM_RESOURCE_PORT_16_BIT_DECODE;
|
|
|
|
Descriptor->u.Port.Length = 0x01;
|
|
|
|
Descriptor->u.Port.Start.LowPart = Ports[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
IsaPdoQueryResourceRequirements(
|
|
|
|
IN PISAPNP_PDO_EXTENSION PdoExt,
|
|
|
|
IN PIRP Irp,
|
|
|
|
IN PIO_STACK_LOCATION IrpSp)
|
|
|
|
{
|
|
|
|
USHORT Ports[] = { ISAPNP_WRITE_DATA, ISAPNP_ADDRESS, 0x274, 0x3e4, 0x204, 0x2e4, 0x354, 0x2f4 };
|
|
|
|
ULONG ListSize, i;
|
|
|
|
PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList;
|
|
|
|
PIO_RESOURCE_DESCRIPTOR Descriptor;
|
|
|
|
|
|
|
|
ListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST)
|
|
|
|
+ 2 * ARRAYSIZE(Ports) * sizeof(IO_RESOURCE_DESCRIPTOR);
|
|
|
|
RequirementsList = ExAllocatePool(NonPagedPool, ListSize);
|
|
|
|
if (!RequirementsList)
|
|
|
|
return STATUS_NO_MEMORY;
|
|
|
|
|
|
|
|
RtlZeroMemory(RequirementsList, ListSize);
|
|
|
|
RequirementsList->ListSize = ListSize;
|
|
|
|
RequirementsList->AlternativeLists = 1;
|
|
|
|
|
|
|
|
RequirementsList->List[0].Version = 1;
|
|
|
|
RequirementsList->List[0].Revision = 1;
|
|
|
|
RequirementsList->List[0].Count = 2 * ARRAYSIZE(Ports);
|
|
|
|
|
|
|
|
for (i = 0; i < 2 * ARRAYSIZE(Ports); i += 2)
|
|
|
|
{
|
|
|
|
Descriptor = &RequirementsList->List[0].Descriptors[i];
|
|
|
|
|
|
|
|
/* Expected port */
|
|
|
|
Descriptor[0].Type = CmResourceTypePort;
|
|
|
|
Descriptor[0].ShareDisposition = CmResourceShareDeviceExclusive;
|
|
|
|
Descriptor[0].Flags = CM_RESOURCE_PORT_16_BIT_DECODE;
|
|
|
|
Descriptor[0].u.Port.Length = Ports[i / 2] & 1 ? 0x01 : 0x04;
|
|
|
|
Descriptor[0].u.Port.Alignment = 0x01;
|
|
|
|
Descriptor[0].u.Port.MinimumAddress.LowPart = Ports[i / 2];
|
|
|
|
Descriptor[0].u.Port.MaximumAddress.LowPart = Ports[i / 2] + Descriptor[0].u.Port.Length - 1;
|
|
|
|
|
|
|
|
/* ... but mark it as optional */
|
|
|
|
Descriptor[1].Option = IO_RESOURCE_ALTERNATIVE;
|
|
|
|
Descriptor[1].Type = CmResourceTypePort;
|
|
|
|
Descriptor[1].ShareDisposition = CmResourceShareDeviceExclusive;
|
|
|
|
Descriptor[1].Flags = CM_RESOURCE_PORT_16_BIT_DECODE;
|
|
|
|
Descriptor[1].u.Port.Alignment = 0x01;
|
|
|
|
}
|
|
|
|
|
|
|
|
Irp->IoStatus.Information = (ULONG_PTR)RequirementsList;
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2010-04-07 20:19:29 +00:00
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
IsaPdoPnp(
|
2020-03-20 18:19:30 +00:00
|
|
|
IN PISAPNP_PDO_EXTENSION PdoExt,
|
|
|
|
IN PIRP Irp,
|
|
|
|
IN PIO_STACK_LOCATION IrpSp)
|
2010-04-07 20:19:29 +00:00
|
|
|
{
|
2020-03-20 18:19:30 +00:00
|
|
|
NTSTATUS Status = Irp->IoStatus.Status;
|
2010-04-07 20:19:29 +00:00
|
|
|
|
2020-03-20 18:19:30 +00:00
|
|
|
switch (IrpSp->MinorFunction)
|
|
|
|
{
|
2020-03-16 19:50:29 +00:00
|
|
|
case IRP_MN_START_DEVICE:
|
|
|
|
if (PdoExt->IsaPnpDevice)
|
|
|
|
Status = IsaHwActivateDevice(PdoExt->IsaPnpDevice);
|
|
|
|
else
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
|
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
PdoExt->Common.State = dsStarted;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IRP_MN_STOP_DEVICE:
|
|
|
|
if (PdoExt->IsaPnpDevice)
|
|
|
|
Status = IsaHwDeactivateDevice(PdoExt->IsaPnpDevice);
|
|
|
|
else
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
|
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
PdoExt->Common.State = dsStopped;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IRP_MN_QUERY_DEVICE_RELATIONS:
|
|
|
|
Status = IsaPdoQueryDeviceRelations(PdoExt, Irp, IrpSp);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IRP_MN_QUERY_CAPABILITIES:
|
|
|
|
Status = IsaPdoQueryCapabilities(PdoExt, Irp, IrpSp);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IRP_MN_QUERY_RESOURCES:
|
|
|
|
if (PdoExt->Common.Self == PdoExt->FdoExt->DataPortPdo)
|
|
|
|
Status = IsaPdoQueryResources(PdoExt, Irp, IrpSp);
|
|
|
|
else
|
|
|
|
DPRINT1("IRP_MN_QUERY_RESOURCES is UNIMPLEMENTED!\n");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
|
|
|
|
if (PdoExt->Common.Self == PdoExt->FdoExt->DataPortPdo)
|
|
|
|
Status = IsaPdoQueryResourceRequirements(PdoExt, Irp, IrpSp);
|
|
|
|
else
|
|
|
|
DPRINT1("IRP_MN_QUERY_RESOURCE_REQUIREMENTS is UNIMPLEMENTED!\n");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IRP_MN_QUERY_ID:
|
|
|
|
Status = IsaPdoQueryId(PdoExt, Irp, IrpSp);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
DPRINT1("Unknown PnP code: %x\n", IrpSp->MinorFunction);
|
|
|
|
break;
|
2020-03-20 18:19:30 +00:00
|
|
|
}
|
2010-04-07 20:19:29 +00:00
|
|
|
|
2020-03-20 18:19:30 +00:00
|
|
|
Irp->IoStatus.Status = Status;
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
2010-04-07 20:19:29 +00:00
|
|
|
|
2020-03-20 18:19:30 +00:00
|
|
|
return Status;
|
2010-04-07 20:19:29 +00:00
|
|
|
}
|