xref: /reactos/drivers/bus/isapnp/fdo.c (revision 2196a06f)
1 /*
2  * PROJECT:         ReactOS ISA PnP Bus driver
3  * LICENSE:         GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4  * PURPOSE:         FDO-specific code
5  * COPYRIGHT:       Copyright 2010 Cameron Gutman <cameron.gutman@reactos.org>
6  *                  Copyright 2020 Hervé Poussineau <hpoussin@reactos.org>
7  *                  Copyright 2021 Dmitry Borisov <di.sean@protonmail.com>
8  */
9 
10 #include "isapnp.h"
11 
12 #define NDEBUG
13 #include <debug.h>
14 
15 static
16 CODE_SEG("PAGE")
17 NTSTATUS
18 IsaFdoStartDevice(
19     _In_ PISAPNP_FDO_EXTENSION FdoExt,
20     _Inout_ PIRP Irp)
21 {
22     NTSTATUS Status;
23 
24     PAGED_CODE();
25 
26     if (!IoForwardIrpSynchronously(FdoExt->Ldo, Irp))
27     {
28         return STATUS_UNSUCCESSFUL;
29     }
30     Status = Irp->IoStatus.Status;
31     if (!NT_SUCCESS(Status))
32     {
33         return Status;
34     }
35 
36     FdoExt->Common.State = dsStarted;
37 
38     return STATUS_SUCCESS;
39 }
40 
41 static
42 CODE_SEG("PAGE")
43 NTSTATUS
44 IsaFdoQueryBusRelations(
45     _In_ PISAPNP_FDO_EXTENSION FdoExt,
46     _Inout_ PIRP Irp)
47 {
48     PAGED_CODE();
49 
50     return IsaPnpFillDeviceRelations(FdoExt, Irp, TRUE);
51 }
52 
53 static
54 CODE_SEG("PAGE")
55 NTSTATUS
56 IsaFdoRemoveDevice(
57     _In_ PISAPNP_FDO_EXTENSION FdoExt,
58     _Inout_ PIRP Irp)
59 {
60     NTSTATUS Status;
61     PLIST_ENTRY Entry;
62 
63     PAGED_CODE();
64 
65     IsaPnpAcquireDeviceDataLock(FdoExt);
66 
67     /* Remove our logical devices */
68     while (!IsListEmpty(&FdoExt->DeviceListHead))
69     {
70         PISAPNP_LOGICAL_DEVICE LogDevice = CONTAINING_RECORD(RemoveHeadList(&FdoExt->
71                                                                             DeviceListHead),
72                                                              ISAPNP_LOGICAL_DEVICE,
73                                                              DeviceLink);
74 
75         --FdoExt->DeviceCount;
76 
77         if (LogDevice->Pdo)
78         {
79             IsaPnpRemoveLogicalDeviceDO(LogDevice->Pdo);
80         }
81     }
82 
83     IsaPnpReleaseDeviceDataLock(FdoExt);
84 
85     IsaPnpAcquireBusDataLock();
86 
87     /* Remove the Read Port */
88     if (FdoExt->ReadPortPdo)
89     {
90         IsaPnpRemoveReadPortDO(FdoExt->ReadPortPdo);
91         ReadPortCreated = FALSE;
92     }
93 
94     /* Find the next ISA bus, if any */
95     Entry = BusListHead.Flink;
96     if (Entry != &BusListHead)
97     {
98         PISAPNP_FDO_EXTENSION NextIsaBus = CONTAINING_RECORD(Entry,
99                                                              ISAPNP_FDO_EXTENSION,
100                                                              BusLink);
101 
102         /* Create a new Read Port for it */
103         if (!ReadPortCreated)
104             IoInvalidateDeviceRelations(NextIsaBus->Pdo, BusRelations);
105     }
106 
107     RemoveEntryList(&FdoExt->BusLink);
108 
109     IsaPnpReleaseBusDataLock();
110 
111     Irp->IoStatus.Status = STATUS_SUCCESS;
112     IoSkipCurrentIrpStackLocation(Irp);
113     Status = IoCallDriver(FdoExt->Ldo, Irp);
114 
115     IoDetachDevice(FdoExt->Ldo);
116     IoDeleteDevice(FdoExt->Common.Self);
117 
118     return Status;
119 }
120 
121 CODE_SEG("PAGE")
122 NTSTATUS
123 IsaFdoPnp(
124     _In_ PISAPNP_FDO_EXTENSION FdoExt,
125     _Inout_ PIRP Irp,
126     _In_ PIO_STACK_LOCATION IrpSp)
127 {
128     NTSTATUS Status;
129 
130     PAGED_CODE();
131 
132     DPRINT("%s(%p, %p) FDO %lu, Minor - %X\n",
133            __FUNCTION__,
134            FdoExt,
135            Irp,
136            FdoExt->BusNumber,
137            IrpSp->MinorFunction);
138 
139     switch (IrpSp->MinorFunction)
140     {
141         case IRP_MN_START_DEVICE:
142             Status = IsaFdoStartDevice(FdoExt, Irp);
143 
144             Irp->IoStatus.Status = Status;
145             IoCompleteRequest(Irp, IO_NO_INCREMENT);
146             return Status;
147 
148         case IRP_MN_QUERY_DEVICE_RELATIONS:
149         {
150             if (IrpSp->Parameters.QueryDeviceRelations.Type != BusRelations)
151                 break;
152 
153             Status = IsaFdoQueryBusRelations(FdoExt, Irp);
154             if (!NT_SUCCESS(Status))
155             {
156                 Irp->IoStatus.Status = Status;
157                 IoCompleteRequest(Irp, IO_NO_INCREMENT);
158 
159                 return Status;
160             }
161 
162             Irp->IoStatus.Status = Status;
163             break;
164         }
165 
166         case IRP_MN_REMOVE_DEVICE:
167             return IsaFdoRemoveDevice(FdoExt, Irp);
168 
169         case IRP_MN_QUERY_PNP_DEVICE_STATE:
170             Irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE;
171             Irp->IoStatus.Status = STATUS_SUCCESS;
172             break;
173 
174         case IRP_MN_QUERY_INTERFACE:
175         {
176             Status = IsaFdoQueryInterface(FdoExt, IrpSp);
177             if (Status == STATUS_NOT_SUPPORTED)
178             {
179                 break;
180             }
181             else if (!NT_SUCCESS(Status))
182             {
183                 Irp->IoStatus.Status = Status;
184                 IoCompleteRequest(Irp, IO_NO_INCREMENT);
185 
186                 return Status;
187             }
188 
189             Irp->IoStatus.Status = Status;
190             break;
191         }
192 
193         case IRP_MN_SURPRISE_REMOVAL:
194         case IRP_MN_QUERY_STOP_DEVICE:
195         case IRP_MN_QUERY_REMOVE_DEVICE:
196         case IRP_MN_CANCEL_STOP_DEVICE:
197         case IRP_MN_CANCEL_REMOVE_DEVICE:
198         case IRP_MN_STOP_DEVICE:
199             Irp->IoStatus.Status = STATUS_SUCCESS;
200             break;
201 
202         default:
203             DPRINT("Unknown PnP code: %X\n", IrpSp->MinorFunction);
204             break;
205     }
206 
207     IoSkipCurrentIrpStackLocation(Irp);
208 
209     return IoCallDriver(FdoExt->Ldo, Irp);
210 }
211