[CRT] Massively improve performance of rand_s
[reactos.git] / drivers / bus / isapnp / fdo.c
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 }