mirror of
https://github.com/reactos/reactos.git
synced 2024-08-19 18:02:55 +00:00
![Dmitry Borisov](/assets/img/avatar_default.png)
- Implement device removal.
- Finish the Read Port special handling
introduced in 21514e473f
.
- Gracefully handle low memory situations.
- Implement IRQ translator.
- Correctly stub power IRP handling.
- Remove unneeded dispatch routines; implement WMI IRP handling.
- Do not handle requests like WRITE_CONFIG.
- Add a signature member to device extensions to make checks clearer.
211 lines
5.1 KiB
C
211 lines
5.1 KiB
C
/*
|
|
* PROJECT: ReactOS ISA PnP Bus driver
|
|
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
|
* PURPOSE: FDO-specific code
|
|
* COPYRIGHT: Copyright 2010 Cameron Gutman <cameron.gutman@reactos.org>
|
|
* Copyright 2020 Hervé Poussineau <hpoussin@reactos.org>
|
|
* Copyright 2021 Dmitry Borisov <di.sean@protonmail.com>
|
|
*/
|
|
|
|
#include "isapnp.h"
|
|
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
|
|
static
|
|
CODE_SEG("PAGE")
|
|
NTSTATUS
|
|
IsaFdoStartDevice(
|
|
_In_ PISAPNP_FDO_EXTENSION FdoExt,
|
|
_Inout_ PIRP Irp)
|
|
{
|
|
NTSTATUS Status;
|
|
|
|
PAGED_CODE();
|
|
|
|
if (!IoForwardIrpSynchronously(FdoExt->Ldo, Irp))
|
|
{
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
Status = Irp->IoStatus.Status;
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
return Status;
|
|
}
|
|
|
|
FdoExt->Common.State = dsStarted;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
static
|
|
CODE_SEG("PAGE")
|
|
NTSTATUS
|
|
IsaFdoQueryBusRelations(
|
|
_In_ PISAPNP_FDO_EXTENSION FdoExt,
|
|
_Inout_ PIRP Irp)
|
|
{
|
|
PAGED_CODE();
|
|
|
|
return IsaPnpFillDeviceRelations(FdoExt, Irp, TRUE);
|
|
}
|
|
|
|
static
|
|
CODE_SEG("PAGE")
|
|
NTSTATUS
|
|
IsaFdoRemoveDevice(
|
|
_In_ PISAPNP_FDO_EXTENSION FdoExt,
|
|
_Inout_ PIRP Irp)
|
|
{
|
|
NTSTATUS Status;
|
|
PLIST_ENTRY Entry;
|
|
|
|
PAGED_CODE();
|
|
|
|
IsaPnpAcquireDeviceDataLock(FdoExt);
|
|
|
|
/* Remove our logical devices */
|
|
while (!IsListEmpty(&FdoExt->DeviceListHead))
|
|
{
|
|
PISAPNP_LOGICAL_DEVICE LogDevice = CONTAINING_RECORD(RemoveHeadList(&FdoExt->
|
|
DeviceListHead),
|
|
ISAPNP_LOGICAL_DEVICE,
|
|
DeviceLink);
|
|
|
|
--FdoExt->DeviceCount;
|
|
|
|
if (LogDevice->Pdo)
|
|
{
|
|
IsaPnpRemoveLogicalDeviceDO(LogDevice->Pdo);
|
|
}
|
|
}
|
|
|
|
IsaPnpReleaseDeviceDataLock(FdoExt);
|
|
|
|
IsaPnpAcquireBusDataLock();
|
|
|
|
/* Remove the Read Port */
|
|
if (FdoExt->ReadPortPdo)
|
|
{
|
|
IsaPnpRemoveReadPortDO(FdoExt->ReadPortPdo);
|
|
ReadPortCreated = FALSE;
|
|
}
|
|
|
|
/* Find the next ISA bus, if any */
|
|
Entry = BusListHead.Flink;
|
|
if (Entry != &BusListHead)
|
|
{
|
|
PISAPNP_FDO_EXTENSION NextIsaBus = CONTAINING_RECORD(Entry,
|
|
ISAPNP_FDO_EXTENSION,
|
|
BusLink);
|
|
|
|
/* Create a new Read Port for it */
|
|
if (!ReadPortCreated)
|
|
IoInvalidateDeviceRelations(NextIsaBus->Pdo, BusRelations);
|
|
}
|
|
|
|
RemoveEntryList(&FdoExt->BusLink);
|
|
|
|
IsaPnpReleaseBusDataLock();
|
|
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
IoSkipCurrentIrpStackLocation(Irp);
|
|
Status = IoCallDriver(FdoExt->Ldo, Irp);
|
|
|
|
IoDetachDevice(FdoExt->Ldo);
|
|
IoDeleteDevice(FdoExt->Common.Self);
|
|
|
|
return Status;
|
|
}
|
|
|
|
CODE_SEG("PAGE")
|
|
NTSTATUS
|
|
IsaFdoPnp(
|
|
_In_ PISAPNP_FDO_EXTENSION FdoExt,
|
|
_Inout_ PIRP Irp,
|
|
_In_ PIO_STACK_LOCATION IrpSp)
|
|
{
|
|
NTSTATUS Status;
|
|
|
|
PAGED_CODE();
|
|
|
|
DPRINT("%s(%p, %p) FDO %lu, Minor - %X\n",
|
|
__FUNCTION__,
|
|
FdoExt,
|
|
Irp,
|
|
FdoExt->BusNumber,
|
|
IrpSp->MinorFunction);
|
|
|
|
switch (IrpSp->MinorFunction)
|
|
{
|
|
case IRP_MN_START_DEVICE:
|
|
Status = IsaFdoStartDevice(FdoExt, Irp);
|
|
|
|
Irp->IoStatus.Status = Status;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
return Status;
|
|
|
|
case IRP_MN_QUERY_DEVICE_RELATIONS:
|
|
{
|
|
if (IrpSp->Parameters.QueryDeviceRelations.Type != BusRelations)
|
|
break;
|
|
|
|
Status = IsaFdoQueryBusRelations(FdoExt, Irp);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
Irp->IoStatus.Status = Status;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return Status;
|
|
}
|
|
|
|
Irp->IoStatus.Status = Status;
|
|
break;
|
|
}
|
|
|
|
case IRP_MN_REMOVE_DEVICE:
|
|
return IsaFdoRemoveDevice(FdoExt, Irp);
|
|
|
|
case IRP_MN_QUERY_PNP_DEVICE_STATE:
|
|
Irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE;
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
break;
|
|
|
|
case IRP_MN_QUERY_INTERFACE:
|
|
{
|
|
Status = IsaFdoQueryInterface(FdoExt, IrpSp);
|
|
if (Status == STATUS_NOT_SUPPORTED)
|
|
{
|
|
break;
|
|
}
|
|
else if (!NT_SUCCESS(Status))
|
|
{
|
|
Irp->IoStatus.Status = Status;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return Status;
|
|
}
|
|
|
|
Irp->IoStatus.Status = Status;
|
|
break;
|
|
}
|
|
|
|
case IRP_MN_SURPRISE_REMOVAL:
|
|
case IRP_MN_QUERY_STOP_DEVICE:
|
|
case IRP_MN_QUERY_REMOVE_DEVICE:
|
|
case IRP_MN_CANCEL_STOP_DEVICE:
|
|
case IRP_MN_CANCEL_REMOVE_DEVICE:
|
|
case IRP_MN_STOP_DEVICE:
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
break;
|
|
|
|
default:
|
|
DPRINT("Unknown PnP code: %X\n", IrpSp->MinorFunction);
|
|
break;
|
|
}
|
|
|
|
IoSkipCurrentIrpStackLocation(Irp);
|
|
|
|
return IoCallDriver(FdoExt->Ldo, Irp);
|
|
}
|