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 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 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 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 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 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 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 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 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