xref: /reactos/drivers/storage/ide/pciidex/pciidex.c (revision c0c57e23)
1 /*
2  * PROJECT:     PCI IDE bus driver extension
3  * LICENSE:     See COPYING in the top level directory
4  * PURPOSE:     Main file
5  * COPYRIGHT:   Copyright 2005 Hervé Poussineau <hpoussin@reactos.org>
6  */
7 
8 #include "pciidex.h"
9 
10 #define NDEBUG
11 #include <debug.h>
12 
13 ULONG PciIdeControllerNumber = 0;
14 
15 CODE_SEG("PAGE")
16 NTSTATUS
17 NTAPI
PciIdeXDispatchWmi(_In_ PDEVICE_OBJECT DeviceObject,_Inout_ PIRP Irp)18 PciIdeXDispatchWmi(
19     _In_ PDEVICE_OBJECT DeviceObject,
20     _Inout_ PIRP Irp)
21 {
22     NTSTATUS Status;
23 
24     PAGED_CODE();
25 
26     if (IS_FDO(DeviceObject->DeviceExtension))
27     {
28         PFDO_DEVICE_EXTENSION FdoExtension = DeviceObject->DeviceExtension;
29 
30         IoSkipCurrentIrpStackLocation(Irp);
31         Status = IoCallDriver(FdoExtension->Ldo, Irp);
32     }
33     else
34     {
35         Status = Irp->IoStatus.Status;
36         IoCompleteRequest(Irp, IO_NO_INCREMENT);
37     }
38 
39     return Status;
40 }
41 
42 CODE_SEG("PAGE")
43 VOID
44 NTAPI
PciIdeXUnload(_In_ PDRIVER_OBJECT DriverObject)45 PciIdeXUnload(
46     _In_ PDRIVER_OBJECT DriverObject)
47 {
48     UNREFERENCED_PARAMETER(DriverObject);
49 
50     PAGED_CODE();
51 
52     NOTHING;
53 }
54 
55 static
56 CODE_SEG("PAGE")
57 NTSTATUS
PciIdeXQueryInterface(_In_ PFDO_DEVICE_EXTENSION FdoExtension,_In_ const GUID * Guid,_Out_ PVOID Interface,_In_ ULONG Size)58 PciIdeXQueryInterface(
59     _In_ PFDO_DEVICE_EXTENSION FdoExtension,
60     _In_ const GUID* Guid,
61     _Out_ PVOID Interface,
62     _In_ ULONG Size)
63 {
64     KEVENT Event;
65     IO_STATUS_BLOCK IoStatus;
66     PIRP Irp;
67     PIO_STACK_LOCATION Stack;
68     NTSTATUS Status;
69 
70     PAGED_CODE();
71 
72     KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
73 
74     Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,
75                                        FdoExtension->Ldo,
76                                        NULL,
77                                        0,
78                                        NULL,
79                                        &Event,
80                                        &IoStatus);
81     if (!Irp)
82         return STATUS_INSUFFICIENT_RESOURCES;
83 
84     Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
85     Irp->IoStatus.Information = 0;
86 
87     Stack = IoGetNextIrpStackLocation(Irp);
88     Stack->MinorFunction = IRP_MN_QUERY_INTERFACE;
89     Stack->Parameters.QueryInterface.InterfaceType = Guid;
90     Stack->Parameters.QueryInterface.Version = 1;
91     Stack->Parameters.QueryInterface.Size = Size;
92     Stack->Parameters.QueryInterface.Interface = Interface;
93     Stack->Parameters.QueryInterface.InterfaceSpecificData = NULL;
94 
95     Status = IoCallDriver(FdoExtension->Ldo, Irp);
96     if (Status == STATUS_PENDING)
97     {
98         KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
99         Status = IoStatus.Status;
100     }
101 
102     return Status;
103 }
104 
105 static
106 CODE_SEG("PAGE")
107 NTSTATUS
PciIdeXGetConfigurationInfo(_In_ PFDO_DEVICE_EXTENSION FdoExtension)108 PciIdeXGetConfigurationInfo(
109     _In_ PFDO_DEVICE_EXTENSION FdoExtension)
110 {
111     UCHAR Buffer[RTL_SIZEOF_THROUGH_FIELD(PCI_COMMON_HEADER, BaseClass)];
112     PPCI_COMMON_HEADER PciConfig = (PPCI_COMMON_HEADER)Buffer;
113     ULONG BytesRead;
114 
115     PAGED_CODE();
116 
117     BytesRead = (*FdoExtension->BusInterface.GetBusData)(FdoExtension->BusInterface.Context,
118                                                          PCI_WHICHSPACE_CONFIG,
119                                                          Buffer,
120                                                          0,
121                                                          sizeof(Buffer));
122     if (BytesRead != sizeof(Buffer))
123         return STATUS_IO_DEVICE_ERROR;
124 
125     FdoExtension->VendorId = PciConfig->VendorID;
126     FdoExtension->DeviceId = PciConfig->DeviceID;
127 
128     if (PciConfig->BaseClass == PCI_CLASS_MASS_STORAGE_CTLR)
129     {
130         if (PciConfig->SubClass == PCI_SUBCLASS_MSC_IDE_CTLR)
131         {
132             /* Both IDE channels in native mode */
133             FdoExtension->InNativeMode =
134                 (PciConfig->ProgIf & PCIIDE_PROGIF_PRIMARY_CHANNEL_NATIVE_MODE) &&
135                 (PciConfig->ProgIf & PCIIDE_PROGIF_SECONDARY_CHANNEL_NATIVE_MODE);
136         }
137         else if (PciConfig->SubClass == PCI_SUBCLASS_MSC_RAID_CTLR)
138         {
139             FdoExtension->InNativeMode = TRUE;
140         }
141     }
142 
143     DPRINT("Controller %04x:%04x, Interface byte 0x%02x, Native mode %d\n",
144            FdoExtension->VendorId,
145            FdoExtension->DeviceId,
146            PciConfig->ProgIf,
147            FdoExtension->InNativeMode);
148 
149     return STATUS_SUCCESS;
150 }
151 
152 CODE_SEG("PAGE")
153 NTSTATUS
154 NTAPI
PciIdeXAddDevice(_In_ PDRIVER_OBJECT DriverObject,_In_ PDEVICE_OBJECT PhysicalDeviceObject)155 PciIdeXAddDevice(
156     _In_ PDRIVER_OBJECT DriverObject,
157     _In_ PDEVICE_OBJECT PhysicalDeviceObject)
158 {
159     PPCIIDEX_DRIVER_EXTENSION DriverExtension;
160     PFDO_DEVICE_EXTENSION FdoExtension;
161     ULONG DeviceExtensionSize;
162     PDEVICE_OBJECT Fdo;
163     UNICODE_STRING DeviceName;
164     WCHAR DeviceNameBuffer[sizeof("\\Device\\Ide\\PciIde999")];
165     NTSTATUS Status;
166 
167     PAGED_CODE();
168 
169     Status = RtlStringCbPrintfW(DeviceNameBuffer,
170                                 sizeof(DeviceNameBuffer),
171                                 L"\\Device\\Ide\\PciIde%u",
172                                 PciIdeControllerNumber);
173     ASSERT(NT_SUCCESS(Status));
174     RtlInitUnicodeString(&DeviceName, DeviceNameBuffer);
175 
176     DPRINT("%s(%p, %p) '%wZ'\n", __FUNCTION__, DriverObject, PhysicalDeviceObject, &DeviceName);
177 
178     DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
179     ASSERT(DriverExtension);
180 
181     Status = RtlULongAdd(DriverExtension->MiniControllerExtensionSize,
182                          sizeof(FDO_DEVICE_EXTENSION),
183                          &DeviceExtensionSize);
184     if (!NT_SUCCESS(Status))
185     {
186         DPRINT1("Invalid miniport extension size %lx\n",
187                 DriverExtension->MiniControllerExtensionSize);
188         return Status;
189     }
190 
191     Status = IoCreateDevice(DriverObject,
192                             DeviceExtensionSize,
193                             &DeviceName,
194                             FILE_DEVICE_BUS_EXTENDER,
195                             FILE_DEVICE_SECURE_OPEN,
196                             FALSE,
197                             &Fdo);
198     if (!NT_SUCCESS(Status))
199     {
200         DPRINT1("Failed to create FDO 0x%lx\n", Status);
201         return Status;
202     }
203 
204     FdoExtension = Fdo->DeviceExtension;
205 
206     RtlZeroMemory(FdoExtension, sizeof(FDO_DEVICE_EXTENSION));
207     FdoExtension->Common.IsFDO = TRUE;
208     FdoExtension->Common.Self = Fdo;
209     FdoExtension->DriverObject = DriverObject;
210     FdoExtension->ControllerNumber = PciIdeControllerNumber++;
211 
212     KeInitializeSpinLock(&FdoExtension->BusDataLock);
213     ExInitializeFastMutex(&FdoExtension->DeviceSyncMutex);
214 
215     Status = IoAttachDeviceToDeviceStackSafe(Fdo, PhysicalDeviceObject, &FdoExtension->Ldo);
216     if (!NT_SUCCESS(Status))
217     {
218         DPRINT("Failed to attach FDO 0x%lx\n", Status);
219         goto Failure;
220     }
221 
222     /* DMA buffers alignment */
223     Fdo->AlignmentRequirement = max(FdoExtension->Ldo->AlignmentRequirement, FILE_WORD_ALIGNMENT);
224 
225     Status = PciIdeXQueryInterface(FdoExtension,
226                                    &GUID_BUS_INTERFACE_STANDARD,
227                                    &FdoExtension->BusInterface,
228                                    sizeof(BUS_INTERFACE_STANDARD));
229     if (!NT_SUCCESS(Status))
230     {
231         DPRINT1("No bus interface 0x%lx\n", Status);
232         goto Failure;
233     }
234 
235     Status = PciIdeXGetConfigurationInfo(FdoExtension);
236     if (!NT_SUCCESS(Status))
237     {
238         DPRINT1("Unable to retrieve the configuration info %lx\n", Status);
239         goto Failure;
240     }
241 
242     Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
243 
244     return STATUS_SUCCESS;
245 
246 Failure:
247     if (FdoExtension->Ldo)
248         IoDetachDevice(FdoExtension->Ldo);
249 
250     IoDeleteDevice(Fdo);
251 
252     return Status;
253 }
254 
255 static
256 CODE_SEG("PAGE")
257 VOID
PciIdeXCreateIdeDirectory(VOID)258 PciIdeXCreateIdeDirectory(VOID)
259 {
260     HANDLE Handle;
261     NTSTATUS Status;
262     OBJECT_ATTRIBUTES ObjectAttributes;
263     UNICODE_STRING DirectoryName = RTL_CONSTANT_STRING(L"\\Device\\Ide");
264 
265     PAGED_CODE();
266 
267     InitializeObjectAttributes(&ObjectAttributes,
268                                &DirectoryName,
269                                OBJ_CASE_INSENSITIVE | OBJ_PERMANENT | OBJ_KERNEL_HANDLE,
270                                NULL,
271                                NULL);
272 
273     Status = ZwCreateDirectoryObject(&Handle, DIRECTORY_ALL_ACCESS, &ObjectAttributes);
274     if (NT_SUCCESS(Status))
275     {
276         /* We don't need a handle for a permanent object */
277         ZwClose(Handle);
278     }
279     /*
280      * Ignore directory creation failures (don't report them as a driver initialization error)
281      * as the directory may have already been created by another driver.
282      * We will handle fatal errors later via IoCreateDevice() call.
283      */
284 }
285 
286 CODE_SEG("PAGE")
287 NTSTATUS
288 NTAPI
PciIdeXInitialize(_In_ PDRIVER_OBJECT DriverObject,_In_ PUNICODE_STRING RegistryPath,_In_ PCONTROLLER_PROPERTIES HwGetControllerProperties,_In_ ULONG ExtensionSize)289 PciIdeXInitialize(
290     _In_ PDRIVER_OBJECT DriverObject,
291     _In_ PUNICODE_STRING RegistryPath,
292     _In_ PCONTROLLER_PROPERTIES HwGetControllerProperties,
293     _In_ ULONG ExtensionSize)
294 {
295     PPCIIDEX_DRIVER_EXTENSION DriverExtension;
296     NTSTATUS Status;
297 
298     PAGED_CODE();
299 
300     DPRINT("PciIdeXInitialize(%p '%wZ' %p 0x%lx)\n",
301            DriverObject, RegistryPath, HwGetControllerProperties, ExtensionSize);
302 
303     Status = IoAllocateDriverObjectExtension(DriverObject,
304                                              DriverObject,
305                                              sizeof(PCIIDEX_DRIVER_EXTENSION),
306                                              (PVOID*)&DriverExtension);
307     if (!NT_SUCCESS(Status))
308         return Status;
309 
310     RtlZeroMemory(DriverExtension, sizeof(PCIIDEX_DRIVER_EXTENSION));
311     DriverExtension->MiniControllerExtensionSize = ExtensionSize;
312     DriverExtension->HwGetControllerProperties = HwGetControllerProperties;
313 
314     DriverObject->MajorFunction[IRP_MJ_PNP] = PciIdeXDispatchPnp;
315     DriverObject->MajorFunction[IRP_MJ_POWER] = PciIdeXDispatchPower;
316     DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = PciIdeXDispatchWmi;
317     DriverObject->DriverExtension->AddDevice = PciIdeXAddDevice;
318     DriverObject->DriverUnload = PciIdeXUnload;
319 
320     /* Create a directory to hold the driver's device objects */
321     PciIdeXCreateIdeDirectory();
322 
323     return STATUS_SUCCESS;
324 }
325 
326 CODE_SEG("PAGE") /* This function is too small to be placed into INIT section */
327 NTSTATUS
328 NTAPI
DriverEntry(_In_ PDRIVER_OBJECT DriverObject,_In_ PUNICODE_STRING RegistryPath)329 DriverEntry(
330     _In_ PDRIVER_OBJECT DriverObject,
331     _In_ PUNICODE_STRING RegistryPath)
332 {
333     UNREFERENCED_PARAMETER(DriverObject);
334     UNREFERENCED_PARAMETER(RegistryPath);
335 
336     PAGED_CODE();
337 
338     return STATUS_SUCCESS;
339 }
340