mirror of
https://github.com/reactos/reactos.git
synced 2025-04-26 16:40:27 +00:00
[ISAPNP] Implement the Read Port resource management
Currently disabled until the kernel is ready
This commit is contained in:
parent
f15de15554
commit
c4b6330b14
3 changed files with 243 additions and 59 deletions
|
@ -370,22 +370,54 @@ IsaForwardOrIgnore(
|
|||
}
|
||||
}
|
||||
|
||||
static
|
||||
CODE_SEG("PAGE")
|
||||
NTSTATUS
|
||||
IsaPnpCreateReadPortDORequirements(
|
||||
_In_ PISAPNP_PDO_EXTENSION PdoExt)
|
||||
_In_ PISAPNP_PDO_EXTENSION PdoExt,
|
||||
_In_opt_ ULONG SelectedReadPort)
|
||||
{
|
||||
ULONG ListSize, i;
|
||||
ULONG ResourceCount, ListSize, i;
|
||||
PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList;
|
||||
PIO_RESOURCE_DESCRIPTOR Descriptor;
|
||||
const ULONG Ports[] = { ISAPNP_WRITE_DATA, ISAPNP_ADDRESS,
|
||||
0x274, 0x3E4, 0x204, 0x2E4, 0x354, 0x2F4 };
|
||||
const ULONG Ports[] = { ISAPNP_WRITE_DATA, ISAPNP_ADDRESS };
|
||||
const ULONG ReadPorts[] = { 0x274, 0x3E4, 0x204, 0x2E4, 0x354, 0x2F4 };
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
ListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST)
|
||||
+ 2 * RTL_NUMBER_OF(Ports) * sizeof(IO_RESOURCE_DESCRIPTOR);
|
||||
if (SelectedReadPort)
|
||||
{
|
||||
/*
|
||||
* [IO descriptor: ISAPNP_WRITE_DATA, required]
|
||||
* [IO descriptor: ISAPNP_WRITE_DATA, optional]
|
||||
* [IO descriptor: ISAPNP_ADDRESS, required]
|
||||
* [IO descriptor: ISAPNP_ADDRESS, optional]
|
||||
* [IO descriptor: Selected Read Port, required]
|
||||
* [IO descriptor: Read Port 1, optional]
|
||||
* [IO descriptor: Read Port 2, optional]
|
||||
* [...]
|
||||
* [IO descriptor: Read Port X - 1, optional]
|
||||
*/
|
||||
ResourceCount = RTL_NUMBER_OF(Ports) * 2 + RTL_NUMBER_OF(ReadPorts);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* [IO descriptor: ISAPNP_WRITE_DATA, required]
|
||||
* [IO descriptor: ISAPNP_WRITE_DATA, optional]
|
||||
* [IO descriptor: ISAPNP_ADDRESS, required]
|
||||
* [IO descriptor: ISAPNP_ADDRESS, optional]
|
||||
* [IO descriptor: Read Port 1, required]
|
||||
* [IO descriptor: Read Port 1, optional]
|
||||
* [IO descriptor: Read Port 2, required]
|
||||
* [IO descriptor: Read Port 2, optional]
|
||||
* [...]
|
||||
* [IO descriptor: Read Port X, required]
|
||||
* [IO descriptor: Read Port X, optional]
|
||||
*/
|
||||
ResourceCount = (RTL_NUMBER_OF(Ports) + RTL_NUMBER_OF(ReadPorts)) * 2;
|
||||
}
|
||||
ListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST) +
|
||||
sizeof(IO_RESOURCE_DESCRIPTOR) * (ResourceCount - 1);
|
||||
RequirementsList = ExAllocatePoolZero(PagedPool, ListSize, TAG_ISAPNP);
|
||||
if (!RequirementsList)
|
||||
return STATUS_NO_MEMORY;
|
||||
|
@ -395,27 +427,92 @@ IsaPnpCreateReadPortDORequirements(
|
|||
|
||||
RequirementsList->List[0].Version = 1;
|
||||
RequirementsList->List[0].Revision = 1;
|
||||
RequirementsList->List[0].Count = 2 * RTL_NUMBER_OF(Ports);
|
||||
RequirementsList->List[0].Count = ResourceCount;
|
||||
|
||||
for (i = 0; i < 2 * RTL_NUMBER_OF(Ports); i += 2)
|
||||
Descriptor = &RequirementsList->List[0].Descriptors[0];
|
||||
|
||||
/* Store the Data port and the Address port */
|
||||
for (i = 0; i < RTL_NUMBER_OF(Ports) * 2; i++)
|
||||
{
|
||||
Descriptor = &RequirementsList->List[0].Descriptors[i];
|
||||
if ((i % 2) == 0)
|
||||
{
|
||||
/* Expected port */
|
||||
Descriptor->Type = CmResourceTypePort;
|
||||
Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
|
||||
Descriptor->Flags = CM_RESOURCE_PORT_16_BIT_DECODE;
|
||||
Descriptor->u.Port.Length = 0x01;
|
||||
Descriptor->u.Port.Alignment = 0x01;
|
||||
Descriptor->u.Port.MinimumAddress.LowPart =
|
||||
Descriptor->u.Port.MaximumAddress.LowPart = Ports[i / 2];
|
||||
}
|
||||
else
|
||||
{
|
||||
/* ... but mark it as optional */
|
||||
Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
|
||||
Descriptor->Type = CmResourceTypePort;
|
||||
Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
|
||||
Descriptor->Flags = CM_RESOURCE_PORT_16_BIT_DECODE;
|
||||
Descriptor->u.Port.Alignment = 0x01;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
Descriptor++;
|
||||
}
|
||||
|
||||
/* ... 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;
|
||||
/* Store the Read Ports */
|
||||
if (SelectedReadPort)
|
||||
{
|
||||
BOOLEAN Selected = FALSE;
|
||||
|
||||
DBG_UNREFERENCED_LOCAL_VARIABLE(Selected);
|
||||
|
||||
for (i = 0; i < RTL_NUMBER_OF(ReadPorts); i++)
|
||||
{
|
||||
if (ReadPorts[i] != SelectedReadPort)
|
||||
Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
|
||||
else
|
||||
Selected = TRUE;
|
||||
Descriptor->Type = CmResourceTypePort;
|
||||
Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
|
||||
Descriptor->Flags = CM_RESOURCE_PORT_16_BIT_DECODE;
|
||||
Descriptor->u.Port.Length = 0x04;
|
||||
Descriptor->u.Port.Alignment = 0x01;
|
||||
Descriptor->u.Port.MinimumAddress.LowPart = ReadPorts[i];
|
||||
Descriptor->u.Port.MaximumAddress.LowPart = ReadPorts[i] +
|
||||
Descriptor->u.Port.Length - 1;
|
||||
|
||||
Descriptor++;
|
||||
}
|
||||
|
||||
ASSERT(Selected == TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < RTL_NUMBER_OF(ReadPorts) * 2; i++)
|
||||
{
|
||||
if ((i % 2) == 0)
|
||||
{
|
||||
/* Expected port */
|
||||
Descriptor->Type = CmResourceTypePort;
|
||||
Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
|
||||
Descriptor->Flags = CM_RESOURCE_PORT_16_BIT_DECODE;
|
||||
Descriptor->u.Port.Length = 0x04;
|
||||
Descriptor->u.Port.Alignment = 0x01;
|
||||
Descriptor->u.Port.MinimumAddress.LowPart = ReadPorts[i / 2];
|
||||
Descriptor->u.Port.MaximumAddress.LowPart = ReadPorts[i / 2] +
|
||||
Descriptor->u.Port.Length - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* ... but mark it as optional */
|
||||
Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
|
||||
Descriptor->Type = CmResourceTypePort;
|
||||
Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
|
||||
Descriptor->Flags = CM_RESOURCE_PORT_16_BIT_DECODE;
|
||||
Descriptor->u.Port.Alignment = 0x01;
|
||||
}
|
||||
|
||||
Descriptor++;
|
||||
}
|
||||
}
|
||||
|
||||
PdoExt->RequirementsList = RequirementsList;
|
||||
|
@ -493,7 +590,7 @@ IsaPnpCreateReadPortDO(
|
|||
PdoExt->Common.State = dsStopped;
|
||||
PdoExt->FdoExt = FdoExt;
|
||||
|
||||
Status = IsaPnpCreateReadPortDORequirements(PdoExt);
|
||||
Status = IsaPnpCreateReadPortDORequirements(PdoExt, 0);
|
||||
if (!NT_SUCCESS(Status))
|
||||
goto Failure;
|
||||
|
||||
|
|
|
@ -115,6 +115,7 @@ typedef struct _ISAPNP_PDO_EXTENSION
|
|||
#define ISAPNP_ENUMERATED 0x00000001 /**< @brief Whether the device has been reported to the PnP manager. */
|
||||
#define ISAPNP_SCANNED_BY_READ_PORT 0x00000002 /**< @brief The bus has been scanned by Read Port PDO. */
|
||||
#define ISAPNP_READ_PORT_ALLOW_FDO_SCAN 0x00000004 /**< @brief Allows the active FDO to scan the bus. */
|
||||
#define ISAPNP_READ_PORT_NEED_REBALANCE 0x00000008 /**< @brief The I/O resource requirements have changed. */
|
||||
|
||||
_Write_guarded_by_(_Global_interlock_)
|
||||
volatile LONG SpecialFiles;
|
||||
|
@ -166,6 +167,12 @@ IsaPnpReleaseDeviceDataLock(
|
|||
|
||||
/* isapnp.c */
|
||||
|
||||
CODE_SEG("PAGE")
|
||||
NTSTATUS
|
||||
IsaPnpCreateReadPortDORequirements(
|
||||
_In_ PISAPNP_PDO_EXTENSION PdoExt,
|
||||
_In_opt_ ULONG SelectedReadPort);
|
||||
|
||||
CODE_SEG("PAGE")
|
||||
VOID
|
||||
IsaPnpRemoveReadPortDO(
|
||||
|
|
|
@ -93,7 +93,14 @@ IsaPdoQueryPnpDeviceState(
|
|||
{
|
||||
PAGED_CODE();
|
||||
|
||||
if (PdoExt->SpecialFiles > 0)
|
||||
if (PdoExt->Flags & ISAPNP_READ_PORT_NEED_REBALANCE)
|
||||
{
|
||||
Irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE |
|
||||
PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED |
|
||||
PNP_DEVICE_FAILED;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
else if (PdoExt->SpecialFiles > 0)
|
||||
{
|
||||
Irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE;
|
||||
return STATUS_SUCCESS;
|
||||
|
@ -368,24 +375,24 @@ IsaPdoQueryResourceRequirements(
|
|||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
#define IS_READ_PORT(_d) ((_d)->Type == CmResourceTypePort && (_d)->u.Port.Length > 1)
|
||||
|
||||
static
|
||||
CODE_SEG("PAGE")
|
||||
NTSTATUS
|
||||
IsaPdoStartReadPort(
|
||||
_In_ PISAPNP_FDO_EXTENSION FdoExt,
|
||||
_In_ PIO_STACK_LOCATION IrpSp)
|
||||
_In_ PISAPNP_PDO_EXTENSION PdoExt,
|
||||
_In_ PCM_RESOURCE_LIST ResourceList)
|
||||
{
|
||||
PISAPNP_PDO_EXTENSION PdoExt = FdoExt->ReadPortPdo->DeviceExtension;
|
||||
PCM_RESOURCE_LIST ResourceList = IrpSp->Parameters.StartDevice.AllocatedResources;
|
||||
NTSTATUS Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
PISAPNP_FDO_EXTENSION FdoExt = PdoExt->FdoExt;
|
||||
NTSTATUS Status;
|
||||
ULONG i;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
if (!ResourceList || ResourceList->Count != 1)
|
||||
if (!ResourceList)
|
||||
{
|
||||
DPRINT1("No resource list (%p) or bad count (%d)\n",
|
||||
ResourceList, ResourceList ? ResourceList->Count : 0);
|
||||
DPRINT1("No resource list\n");
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
|
@ -398,43 +405,110 @@ IsaPdoStartReadPort(
|
|||
return STATUS_REVISION_MISMATCH;
|
||||
}
|
||||
|
||||
for (i = 0; i < ResourceList->List[0].PartialResourceList.Count; i++)
|
||||
#if 0
|
||||
/* Try various Read Ports from the list */
|
||||
if (ResourceList->List[0].PartialResourceList.Count > 3)
|
||||
{
|
||||
PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor =
|
||||
&ResourceList->List[0].PartialResourceList.PartialDescriptors[i];
|
||||
ULONG SelectedPort = 0;
|
||||
|
||||
if (PartialDescriptor->Type == CmResourceTypePort &&
|
||||
PartialDescriptor->u.Port.Length > 1 && !FdoExt->ReadDataPort)
|
||||
for (i = 0; i < ResourceList->List[0].PartialResourceList.Count; i++)
|
||||
{
|
||||
PUCHAR ReadDataPort = ULongToPtr(PartialDescriptor->u.Port.Start.u.LowPart + 3);
|
||||
if (NT_SUCCESS(IsaHwTryReadDataPort(ReadDataPort)))
|
||||
PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor =
|
||||
&ResourceList->List[0].PartialResourceList.PartialDescriptors[i];
|
||||
|
||||
if (IS_READ_PORT(PartialDescriptor))
|
||||
{
|
||||
PUCHAR ReadDataPort = ULongToPtr(PartialDescriptor->u.Port.Start.u.LowPart + 3);
|
||||
|
||||
/*
|
||||
* Remember the first Read Port in the resource list.
|
||||
* It will be selected by default even if no card has been detected.
|
||||
*/
|
||||
if (!SelectedPort)
|
||||
SelectedPort = PartialDescriptor->u.Port.Start.u.LowPart;
|
||||
|
||||
/* We detected some ISAPNP cards */
|
||||
|
||||
FdoExt->ReadDataPort = ReadDataPort;
|
||||
|
||||
IsaPnpAcquireDeviceDataLock(FdoExt);
|
||||
Status = IsaHwFillDeviceList(FdoExt);
|
||||
IsaPnpReleaseDeviceDataLock(FdoExt);
|
||||
|
||||
if (FdoExt->DeviceCount > 0)
|
||||
if (NT_SUCCESS(IsaHwTryReadDataPort(ReadDataPort)))
|
||||
{
|
||||
PdoExt->Flags |= ISAPNP_READ_PORT_ALLOW_FDO_SCAN |
|
||||
ISAPNP_SCANNED_BY_READ_PORT;
|
||||
|
||||
IoInvalidateDeviceRelations(FdoExt->Pdo, BusRelations);
|
||||
IoInvalidateDeviceRelations(FdoExt->ReadPortPdo, RemovalRelations);
|
||||
SelectedPort = PartialDescriptor->u.Port.Start.u.LowPart;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
}
|
||||
|
||||
ASSERT(SelectedPort != 0);
|
||||
|
||||
if (PdoExt->RequirementsList)
|
||||
{
|
||||
ExFreePoolWithTag(PdoExt->RequirementsList, TAG_ISAPNP);
|
||||
PdoExt->RequirementsList = NULL;
|
||||
}
|
||||
|
||||
/* Discard the Read Ports at conflicting locations */
|
||||
Status = IsaPnpCreateReadPortDORequirements(PdoExt, SelectedPort);
|
||||
if (!NT_SUCCESS(Status))
|
||||
return Status;
|
||||
|
||||
PdoExt->Flags |= ISAPNP_READ_PORT_NEED_REBALANCE;
|
||||
|
||||
IoInvalidateDeviceState(PdoExt->Common.Self);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
/* Set the Read Port */
|
||||
else if (ResourceList->List[0].PartialResourceList.Count == 3)
|
||||
#else
|
||||
if (ResourceList->List[0].PartialResourceList.Count > 3) /* Temporary HACK */
|
||||
#endif
|
||||
{
|
||||
PdoExt->Flags &= ~ISAPNP_READ_PORT_NEED_REBALANCE;
|
||||
|
||||
for (i = 0; i < ResourceList->List[0].PartialResourceList.Count; i++)
|
||||
{
|
||||
PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor =
|
||||
&ResourceList->List[0].PartialResourceList.PartialDescriptors[i];
|
||||
|
||||
if (IS_READ_PORT(PartialDescriptor))
|
||||
{
|
||||
/* Mark read data port as started, even if no card has been detected */
|
||||
Status = STATUS_SUCCESS;
|
||||
PUCHAR ReadDataPort = ULongToPtr(PartialDescriptor->u.Port.Start.u.LowPart + 3);
|
||||
|
||||
/* Run the isolation protocol */
|
||||
if (NT_SUCCESS(IsaHwTryReadDataPort(ReadDataPort)))
|
||||
{
|
||||
FdoExt->ReadDataPort = ReadDataPort;
|
||||
|
||||
IsaPnpAcquireDeviceDataLock(FdoExt);
|
||||
|
||||
/* Card identification */
|
||||
Status = IsaHwFillDeviceList(FdoExt);
|
||||
|
||||
if (FdoExt->DeviceCount > 0)
|
||||
{
|
||||
PdoExt->Flags |= ISAPNP_READ_PORT_ALLOW_FDO_SCAN |
|
||||
ISAPNP_SCANNED_BY_READ_PORT;
|
||||
|
||||
IoInvalidateDeviceRelations(FdoExt->Pdo, BusRelations);
|
||||
IoInvalidateDeviceRelations(FdoExt->ReadPortPdo, RemovalRelations);
|
||||
}
|
||||
|
||||
IsaPnpReleaseDeviceDataLock(FdoExt);
|
||||
|
||||
return Status;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return STATUS_DEVICE_CONFIGURATION_ERROR;
|
||||
}
|
||||
|
||||
return Status;
|
||||
/* Mark Read Port as started, even if no card has been detected */
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static
|
||||
|
@ -632,7 +706,10 @@ IsaPdoPnp(
|
|||
if (PdoExt->Common.Signature == IsaPnpLogicalDevice)
|
||||
Status = IsaHwActivateDevice(PdoExt->IsaPnpDevice);
|
||||
else
|
||||
Status = IsaPdoStartReadPort(PdoExt->FdoExt, IrpSp);
|
||||
{
|
||||
Status = IsaPdoStartReadPort(PdoExt,
|
||||
IrpSp->Parameters.StartDevice.AllocatedResources);
|
||||
}
|
||||
|
||||
if (NT_SUCCESS(Status))
|
||||
PdoExt->Common.State = dsStarted;
|
||||
|
@ -655,8 +732,11 @@ IsaPdoPnp(
|
|||
{
|
||||
if (PdoExt->SpecialFiles > 0)
|
||||
Status = STATUS_DEVICE_BUSY;
|
||||
else if (PdoExt->Flags & ISAPNP_READ_PORT_NEED_REBALANCE)
|
||||
Status = STATUS_RESOURCE_REQUIREMENTS_CHANGED;
|
||||
else
|
||||
Status = STATUS_SUCCESS;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue