[PCIIDEX]
[reactos.git] / reactos / drivers / storage / ide / pciidex / miniport.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: PCI IDE bus driver extension
4 * FILE: drivers/storage/pciidex/miniport.c
5 * PURPOSE: Miniport functions
6 * PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.org)
7 */
8
9 #include "pciidex.h"
10
11 #define NDEBUG
12 #include <debug.h>
13
14 static DRIVER_DISPATCH PciIdeXForwardOrIgnore;
15 static NTSTATUS NTAPI
16 PciIdeXForwardOrIgnore(
17 IN PDEVICE_OBJECT DeviceObject,
18 IN PIRP Irp)
19 {
20 if (((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO)
21 return ForwardIrpAndForget(DeviceObject, Irp);
22 else
23 {
24 ULONG MajorFunction = IoGetCurrentIrpStackLocation(Irp)->MajorFunction;
25 NTSTATUS Status;
26
27 if (MajorFunction == IRP_MJ_CREATE ||
28 MajorFunction == IRP_MJ_CLEANUP ||
29 MajorFunction == IRP_MJ_CLOSE)
30 {
31 Status = STATUS_SUCCESS;
32 }
33 else
34 {
35 DPRINT1("PDO stub for major function 0x%lx\n", MajorFunction);
36 Status = STATUS_NOT_SUPPORTED;
37 }
38 Irp->IoStatus.Information = 0;
39 Irp->IoStatus.Status = Status;
40 IoCompleteRequest(Irp, IO_NO_INCREMENT);
41 return Status;
42 }
43 }
44
45 _Dispatch_type_(IRP_MJ_POWER)
46 static DRIVER_DISPATCH PciIdeXPowerDispatch;
47 static NTSTATUS NTAPI
48 PciIdeXPowerDispatch(
49 IN PDEVICE_OBJECT DeviceObject,
50 IN PIRP Irp)
51 {
52 NTSTATUS Status;
53 PIO_STACK_LOCATION IoStack;
54 PDEVICE_OBJECT LowerDevice;
55
56 IoStack = IoGetCurrentIrpStackLocation(Irp);
57 if (((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO)
58 {
59 LowerDevice = ((PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerDevice;
60 PoStartNextPowerIrp(Irp);
61 IoSkipCurrentIrpStackLocation(Irp);
62 return PoCallDriver(LowerDevice, Irp);
63 }
64 else
65 {
66 switch (IoStack->MinorFunction)
67 {
68 case IRP_MN_SET_POWER:
69 case IRP_MN_QUERY_POWER:
70 Irp->IoStatus.Status = STATUS_SUCCESS;
71 break;
72 }
73 Status = Irp->IoStatus.Status;
74 PoStartNextPowerIrp(Irp);
75 IoCompleteRequest(Irp, IO_NO_INCREMENT);
76 return Status;
77 }
78 }
79
80 _Dispatch_type_(IRP_MJ_PNP)
81 static DRIVER_DISPATCH PciIdeXPnpDispatch;
82 static NTSTATUS NTAPI
83 PciIdeXPnpDispatch(
84 IN PDEVICE_OBJECT DeviceObject,
85 IN PIRP Irp)
86 {
87 if (((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO)
88 return PciIdeXFdoPnpDispatch(DeviceObject, Irp);
89 else
90 return PciIdeXPdoPnpDispatch(DeviceObject, Irp);
91 }
92
93 NTSTATUS NTAPI
94 PciIdeXInitialize(
95 IN PDRIVER_OBJECT DriverObject,
96 IN PUNICODE_STRING RegistryPath,
97 IN PCONTROLLER_PROPERTIES HwGetControllerProperties,
98 IN ULONG ExtensionSize)
99 {
100 ULONG i;
101 PPCIIDEX_DRIVER_EXTENSION DriverExtension;
102 NTSTATUS Status;
103
104 DPRINT("PciIdeXInitialize(%p '%wZ' %p 0x%lx)\n",
105 DriverObject, RegistryPath, HwGetControllerProperties, ExtensionSize);
106
107 Status = IoAllocateDriverObjectExtension(
108 DriverObject,
109 DriverObject,
110 sizeof(PCIIDEX_DRIVER_EXTENSION),
111 (PVOID*)&DriverExtension);
112 if (!NT_SUCCESS(Status))
113 return Status;
114 RtlZeroMemory(DriverExtension, sizeof(PCIIDEX_DRIVER_EXTENSION));
115 DriverExtension->MiniControllerExtensionSize = ExtensionSize;
116 DriverExtension->HwGetControllerProperties = HwGetControllerProperties;
117
118 DriverObject->DriverExtension->AddDevice = PciIdeXAddDevice;
119
120 for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
121 DriverObject->MajorFunction[i] = PciIdeXForwardOrIgnore;
122 DriverObject->MajorFunction[IRP_MJ_POWER] = PciIdeXPowerDispatch;
123 DriverObject->MajorFunction[IRP_MJ_PNP] = PciIdeXPnpDispatch;
124
125 return STATUS_SUCCESS;
126 }
127
128 /* May be called at IRQL <= DISPATCH_LEVEL */
129 NTSTATUS NTAPI
130 PciIdeXGetBusData(
131 IN PVOID DeviceExtension,
132 IN PVOID Buffer,
133 IN ULONG ConfigDataOffset,
134 IN ULONG BufferLength)
135 {
136 PFDO_DEVICE_EXTENSION FdoDeviceExtension;
137 ULONG BytesRead;
138 NTSTATUS Status = STATUS_UNSUCCESSFUL;
139
140 DPRINT("PciIdeXGetBusData(%p %p 0x%lx 0x%lx)\n",
141 DeviceExtension, Buffer, ConfigDataOffset, BufferLength);
142
143 FdoDeviceExtension = CONTAINING_RECORD(DeviceExtension, FDO_DEVICE_EXTENSION, MiniControllerExtension);
144 if (FdoDeviceExtension->BusInterface)
145 {
146 BytesRead = (*FdoDeviceExtension->BusInterface->GetBusData)(
147 FdoDeviceExtension->BusInterface->Context,
148 PCI_WHICHSPACE_CONFIG,
149 Buffer,
150 ConfigDataOffset,
151 BufferLength);
152 if (BytesRead == BufferLength)
153 Status = STATUS_SUCCESS;
154 }
155
156 return Status;
157 }
158
159 /* May be called at IRQL <= DISPATCH_LEVEL */
160 NTSTATUS NTAPI
161 PciIdeXSetBusData(
162 IN PVOID DeviceExtension,
163 IN PVOID Buffer,
164 IN PVOID DataMask,
165 IN ULONG ConfigDataOffset,
166 IN ULONG BufferLength)
167 {
168 PFDO_DEVICE_EXTENSION FdoDeviceExtension;
169 PUCHAR CurrentBuffer = NULL;
170 ULONG i, BytesWritten;
171 NTSTATUS Status;
172
173 DPRINT("PciIdeXSetBusData(%p %p %p 0x%lx 0x%lx)\n",
174 DeviceExtension, Buffer, DataMask, ConfigDataOffset, BufferLength);
175
176 CurrentBuffer = ExAllocatePool(NonPagedPool, BufferLength);
177 if (!CurrentBuffer)
178 {
179 Status = STATUS_INSUFFICIENT_RESOURCES;
180 return Status;
181 }
182
183 Status = PciIdeXGetBusData(DeviceExtension, Buffer, ConfigDataOffset, BufferLength);
184 if (!NT_SUCCESS(Status))
185 goto cleanup;
186
187 for (i = 0; i < BufferLength; i++)
188 CurrentBuffer[i] = (CurrentBuffer[i] & ~((PUCHAR)DataMask)[i]) | (((PUCHAR)DataMask)[i] & ((PUCHAR)Buffer)[i]);
189
190 FdoDeviceExtension = CONTAINING_RECORD(DeviceExtension, FDO_DEVICE_EXTENSION, MiniControllerExtension);
191 if (!FdoDeviceExtension->BusInterface)
192 {
193 Status = STATUS_UNSUCCESSFUL;
194 goto cleanup;
195 }
196
197 BytesWritten = (*FdoDeviceExtension->BusInterface->SetBusData)(
198 FdoDeviceExtension->BusInterface->Context,
199 PCI_WHICHSPACE_CONFIG,
200 CurrentBuffer,
201 ConfigDataOffset,
202 BufferLength);
203 if (BytesWritten == BufferLength)
204 Status = STATUS_SUCCESS;
205 else
206 Status = STATUS_UNSUCCESSFUL;
207
208 cleanup:
209 ExFreePool(CurrentBuffer);
210 return Status;
211 }