xref: /reactos/drivers/storage/ide/pciidex/miniport.c (revision 2196a06f)
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 /** @brief Global debugging level. Valid values are between 0 (Error) and 3 (Trace). */
15 ULONG PciIdeDebug = 0;
16 
17 static DRIVER_DISPATCH PciIdeXForwardOrIgnore;
18 static NTSTATUS NTAPI
19 PciIdeXForwardOrIgnore(
20 	IN PDEVICE_OBJECT DeviceObject,
21 	IN PIRP Irp)
22 {
23 	if (((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO)
24 		return ForwardIrpAndForget(DeviceObject, Irp);
25 	else
26 	{
27 		ULONG MajorFunction = IoGetCurrentIrpStackLocation(Irp)->MajorFunction;
28 		NTSTATUS Status;
29 
30 		if (MajorFunction == IRP_MJ_CREATE ||
31 		    MajorFunction == IRP_MJ_CLEANUP ||
32 		    MajorFunction == IRP_MJ_CLOSE)
33 		{
34 			Status = STATUS_SUCCESS;
35 		}
36 		else
37 		{
38 			DPRINT1("PDO stub for major function 0x%lx\n", MajorFunction);
39 			Status = STATUS_NOT_SUPPORTED;
40 		}
41 		Irp->IoStatus.Information = 0;
42 		Irp->IoStatus.Status = Status;
43 		IoCompleteRequest(Irp, IO_NO_INCREMENT);
44 		return Status;
45 	}
46 }
47 
48 _Dispatch_type_(IRP_MJ_POWER)
49 static DRIVER_DISPATCH PciIdeXPowerDispatch;
50 static NTSTATUS NTAPI
51 PciIdeXPowerDispatch(
52 	IN PDEVICE_OBJECT DeviceObject,
53 	IN PIRP Irp)
54 {
55 	NTSTATUS Status;
56 	PIO_STACK_LOCATION IoStack;
57 	PDEVICE_OBJECT LowerDevice;
58 
59 	IoStack = IoGetCurrentIrpStackLocation(Irp);
60 	if (((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO)
61 	{
62 		LowerDevice = ((PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerDevice;
63 		PoStartNextPowerIrp(Irp);
64 		IoSkipCurrentIrpStackLocation(Irp);
65 		return PoCallDriver(LowerDevice, Irp);
66 	}
67 	else
68 	{
69 		switch (IoStack->MinorFunction)
70 		{
71 			case IRP_MN_SET_POWER:
72 			case IRP_MN_QUERY_POWER:
73 				Irp->IoStatus.Status = STATUS_SUCCESS;
74 				break;
75 		}
76 		Status = Irp->IoStatus.Status;
77 		PoStartNextPowerIrp(Irp);
78 		IoCompleteRequest(Irp, IO_NO_INCREMENT);
79 		return Status;
80 	}
81 }
82 
83 _Dispatch_type_(IRP_MJ_PNP)
84 static DRIVER_DISPATCH PciIdeXPnpDispatch;
85 static NTSTATUS NTAPI
86 PciIdeXPnpDispatch(
87 	IN PDEVICE_OBJECT DeviceObject,
88 	IN PIRP Irp)
89 {
90 	if (((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO)
91 		return PciIdeXFdoPnpDispatch(DeviceObject, Irp);
92 	else
93 		return PciIdeXPdoPnpDispatch(DeviceObject, Irp);
94 }
95 
96 /**
97  * @brief Prints the given string with printf-like formatting to the kernel debugger.
98  * @param[in] DebugPrintLevel Level of the debug message.
99  *                            Valid values are between 0 (Error) and 3 (Trace).
100  * @param[in] DebugMessage    Format of the string/arguments.
101  * @param[in] ...             Variable number of arguments matching the format
102  *                            specified in \a DebugMessage.
103  * @sa PciIdeDebug
104  */
105 VOID
106 PciIdeXDebugPrint(
107     _In_ ULONG DebugPrintLevel,
108     _In_z_ _Printf_format_string_ PCCHAR DebugMessage,
109     ...)
110 {
111     va_list ap;
112 
113     /* Check if we can print anything */
114     if (DebugPrintLevel <= PciIdeDebug)
115         DebugPrintLevel = 0;
116 
117     va_start(ap, DebugMessage);
118     vDbgPrintEx(DPFLTR_PCIIDE_ID, DebugPrintLevel, DebugMessage, ap);
119     va_end(ap);
120 }
121 
122 NTSTATUS NTAPI
123 PciIdeXInitialize(
124 	IN PDRIVER_OBJECT DriverObject,
125 	IN PUNICODE_STRING RegistryPath,
126 	IN PCONTROLLER_PROPERTIES HwGetControllerProperties,
127 	IN ULONG ExtensionSize)
128 {
129 	ULONG i;
130 	PPCIIDEX_DRIVER_EXTENSION DriverExtension;
131 	NTSTATUS Status;
132 
133 	DPRINT("PciIdeXInitialize(%p '%wZ' %p 0x%lx)\n",
134 		DriverObject, RegistryPath, HwGetControllerProperties, ExtensionSize);
135 
136 	Status = IoAllocateDriverObjectExtension(
137 		DriverObject,
138 		DriverObject,
139 		sizeof(PCIIDEX_DRIVER_EXTENSION),
140 		(PVOID*)&DriverExtension);
141 	if (!NT_SUCCESS(Status))
142 		return Status;
143 	RtlZeroMemory(DriverExtension, sizeof(PCIIDEX_DRIVER_EXTENSION));
144 	DriverExtension->MiniControllerExtensionSize = ExtensionSize;
145 	DriverExtension->HwGetControllerProperties = HwGetControllerProperties;
146 
147 	DriverObject->DriverExtension->AddDevice = PciIdeXAddDevice;
148 
149 	for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
150 		DriverObject->MajorFunction[i] = PciIdeXForwardOrIgnore;
151 	DriverObject->MajorFunction[IRP_MJ_POWER] = PciIdeXPowerDispatch;
152 	DriverObject->MajorFunction[IRP_MJ_PNP] = PciIdeXPnpDispatch;
153 
154 	return STATUS_SUCCESS;
155 }
156 
157 /* May be called at IRQL <= DISPATCH_LEVEL */
158 NTSTATUS NTAPI
159 PciIdeXGetBusData(
160 	IN PVOID DeviceExtension,
161 	IN PVOID Buffer,
162 	IN ULONG ConfigDataOffset,
163 	IN ULONG BufferLength)
164 {
165 	PFDO_DEVICE_EXTENSION FdoDeviceExtension;
166 	ULONG BytesRead;
167 	NTSTATUS Status = STATUS_UNSUCCESSFUL;
168 
169 	DPRINT("PciIdeXGetBusData(%p %p 0x%lx 0x%lx)\n",
170 		DeviceExtension, Buffer, ConfigDataOffset, BufferLength);
171 
172 	FdoDeviceExtension = CONTAINING_RECORD(DeviceExtension, FDO_DEVICE_EXTENSION, MiniControllerExtension);
173 	if (FdoDeviceExtension->BusInterface)
174 	{
175 		BytesRead = (*FdoDeviceExtension->BusInterface->GetBusData)(
176 			FdoDeviceExtension->BusInterface->Context,
177 			PCI_WHICHSPACE_CONFIG,
178 			Buffer,
179 			ConfigDataOffset,
180 			BufferLength);
181 		if (BytesRead == BufferLength)
182 			Status = STATUS_SUCCESS;
183 	}
184 
185 	return Status;
186 }
187 
188 /* May be called at IRQL <= DISPATCH_LEVEL */
189 NTSTATUS NTAPI
190 PciIdeXSetBusData(
191 	IN PVOID DeviceExtension,
192 	IN PVOID Buffer,
193 	IN PVOID DataMask,
194 	IN ULONG ConfigDataOffset,
195 	IN ULONG BufferLength)
196 {
197 	PFDO_DEVICE_EXTENSION FdoDeviceExtension;
198 	PUCHAR CurrentBuffer = NULL;
199 	ULONG i, BytesWritten;
200 	NTSTATUS Status;
201 
202 	DPRINT("PciIdeXSetBusData(%p %p %p 0x%lx 0x%lx)\n",
203 		DeviceExtension, Buffer, DataMask, ConfigDataOffset, BufferLength);
204 
205 	CurrentBuffer = ExAllocatePool(NonPagedPool, BufferLength);
206 	if (!CurrentBuffer)
207 	{
208 		Status = STATUS_INSUFFICIENT_RESOURCES;
209 		return Status;
210 	}
211 
212 	Status = PciIdeXGetBusData(DeviceExtension, Buffer, ConfigDataOffset, BufferLength);
213 	if (!NT_SUCCESS(Status))
214 		goto cleanup;
215 
216 	for (i = 0; i < BufferLength; i++)
217 		CurrentBuffer[i] = (CurrentBuffer[i] & ~((PUCHAR)DataMask)[i]) | (((PUCHAR)DataMask)[i] & ((PUCHAR)Buffer)[i]);
218 
219 	FdoDeviceExtension = CONTAINING_RECORD(DeviceExtension, FDO_DEVICE_EXTENSION, MiniControllerExtension);
220 	if (!FdoDeviceExtension->BusInterface)
221 	{
222 		Status = STATUS_UNSUCCESSFUL;
223 		goto cleanup;
224 	}
225 
226 	BytesWritten = (*FdoDeviceExtension->BusInterface->SetBusData)(
227 		FdoDeviceExtension->BusInterface->Context,
228 		PCI_WHICHSPACE_CONFIG,
229 		CurrentBuffer,
230 		ConfigDataOffset,
231 		BufferLength);
232 	if (BytesWritten == BufferLength)
233 		Status = STATUS_SUCCESS;
234 	else
235 		Status = STATUS_UNSUCCESSFUL;
236 
237 cleanup:
238 	ExFreePool(CurrentBuffer);
239 	return Status;
240 }
241