Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenfdo.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: PCI IDE bus driver extension 00004 * FILE: drivers/storage/pciidex/fdo.c 00005 * PURPOSE: IRP_MJ_PNP operations for FDOs 00006 * PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.org) 00007 */ 00008 00009 #include "pciidex.h" 00010 00011 #define NDEBUG 00012 #include <debug.h> 00013 00014 static NTSTATUS 00015 GetBusInterface( 00016 IN PFDO_DEVICE_EXTENSION DeviceExtension) 00017 { 00018 PBUS_INTERFACE_STANDARD BusInterface = NULL; 00019 KEVENT Event; 00020 IO_STATUS_BLOCK IoStatus; 00021 PIRP Irp; 00022 PIO_STACK_LOCATION Stack; 00023 NTSTATUS Status = STATUS_UNSUCCESSFUL; 00024 00025 if (DeviceExtension->BusInterface) 00026 { 00027 DPRINT("We already have the bus interface\n"); 00028 goto cleanup; 00029 } 00030 00031 BusInterface = ExAllocatePool(PagedPool, sizeof(BUS_INTERFACE_STANDARD)); 00032 if (!BusInterface) 00033 { 00034 DPRINT("ExAllocatePool() failed\n"); 00035 Status = STATUS_INSUFFICIENT_RESOURCES; 00036 goto cleanup; 00037 } 00038 00039 KeInitializeEvent(&Event, SynchronizationEvent, FALSE); 00040 Irp = IoBuildSynchronousFsdRequest( 00041 IRP_MJ_PNP, 00042 DeviceExtension->LowerDevice, 00043 NULL, 00044 0, 00045 NULL, 00046 &Event, 00047 &IoStatus); 00048 if (!Irp) 00049 { 00050 DPRINT("IoBuildSynchronousFsdRequest() failed\n"); 00051 Status = STATUS_INSUFFICIENT_RESOURCES; 00052 goto cleanup; 00053 } 00054 00055 Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; 00056 Irp->IoStatus.Information = 0; 00057 00058 Stack = IoGetNextIrpStackLocation(Irp); 00059 Stack->MajorFunction = IRP_MJ_PNP; 00060 Stack->MinorFunction = IRP_MN_QUERY_INTERFACE; 00061 Stack->Parameters.QueryInterface.InterfaceType = (LPGUID)&GUID_BUS_INTERFACE_STANDARD; 00062 Stack->Parameters.QueryInterface.Version = 1; 00063 Stack->Parameters.QueryInterface.Size = sizeof(BUS_INTERFACE_STANDARD); 00064 Stack->Parameters.QueryInterface.Interface = (PINTERFACE)BusInterface; 00065 Stack->Parameters.QueryInterface.InterfaceSpecificData = NULL; 00066 00067 Status = IoCallDriver(DeviceExtension->LowerDevice, Irp); 00068 if (Status == STATUS_PENDING) 00069 { 00070 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); 00071 Status = IoStatus.Status; 00072 } 00073 if (!NT_SUCCESS(Status)) 00074 goto cleanup; 00075 00076 DeviceExtension->BusInterface = BusInterface; 00077 BusInterface = NULL; 00078 Status = STATUS_SUCCESS; 00079 00080 cleanup: 00081 if (BusInterface) ExFreePool(BusInterface); 00082 return Status; 00083 } 00084 00085 static NTSTATUS 00086 ReleaseBusInterface( 00087 IN PFDO_DEVICE_EXTENSION DeviceExtension) 00088 { 00089 NTSTATUS Status = STATUS_UNSUCCESSFUL; 00090 00091 if (DeviceExtension->BusInterface) 00092 { 00093 (*DeviceExtension->BusInterface->InterfaceDereference)( 00094 DeviceExtension->BusInterface->Context); 00095 DeviceExtension->BusInterface = NULL; 00096 Status = STATUS_SUCCESS; 00097 } 00098 00099 return Status; 00100 } 00101 00102 NTSTATUS NTAPI 00103 PciIdeXAddDevice( 00104 IN PDRIVER_OBJECT DriverObject, 00105 IN PDEVICE_OBJECT Pdo) 00106 { 00107 PPCIIDEX_DRIVER_EXTENSION DriverExtension; 00108 PFDO_DEVICE_EXTENSION DeviceExtension; 00109 PDEVICE_OBJECT Fdo; 00110 ULONG BytesRead; 00111 PCI_COMMON_CONFIG PciConfig; 00112 NTSTATUS Status; 00113 00114 DPRINT("PciIdeXAddDevice(%p %p)\n", DriverObject, Pdo); 00115 00116 DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject); 00117 ASSERT(DriverExtension); 00118 00119 Status = IoCreateDevice( 00120 DriverObject, 00121 sizeof(FDO_DEVICE_EXTENSION) + DriverExtension->MiniControllerExtensionSize, 00122 NULL, 00123 FILE_DEVICE_BUS_EXTENDER, 00124 FILE_DEVICE_SECURE_OPEN, 00125 TRUE, 00126 &Fdo); 00127 if (!NT_SUCCESS(Status)) 00128 { 00129 DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status); 00130 return Status; 00131 } 00132 00133 DeviceExtension = (PFDO_DEVICE_EXTENSION)Fdo->DeviceExtension; 00134 RtlZeroMemory(DeviceExtension, sizeof(FDO_DEVICE_EXTENSION)); 00135 00136 DeviceExtension->Common.IsFDO = TRUE; 00137 00138 Status = IoAttachDeviceToDeviceStackSafe(Fdo, Pdo, &DeviceExtension->LowerDevice); 00139 if (!NT_SUCCESS(Status)) 00140 { 00141 DPRINT("IoAttachDeviceToDeviceStackSafe() failed with status 0x%08lx\n", Status); 00142 return Status; 00143 } 00144 00145 Status = GetBusInterface(DeviceExtension); 00146 if (!NT_SUCCESS(Status)) 00147 { 00148 DPRINT("GetBusInterface() failed with status 0x%08lx\n", Status); 00149 IoDetachDevice(DeviceExtension->LowerDevice); 00150 return Status; 00151 } 00152 00153 BytesRead = (*DeviceExtension->BusInterface->GetBusData)( 00154 DeviceExtension->BusInterface->Context, 00155 PCI_WHICHSPACE_CONFIG, 00156 &PciConfig, 00157 0, 00158 PCI_COMMON_HDR_LENGTH); 00159 if (BytesRead != PCI_COMMON_HDR_LENGTH) 00160 { 00161 DPRINT("BusInterface->GetBusData() failed()\n"); 00162 ReleaseBusInterface(DeviceExtension); 00163 IoDetachDevice(DeviceExtension->LowerDevice); 00164 return STATUS_IO_DEVICE_ERROR; 00165 } 00166 00167 DeviceExtension->VendorId = PciConfig.VendorID; 00168 DeviceExtension->DeviceId = PciConfig.DeviceID; 00169 00170 Fdo->Flags &= ~DO_DEVICE_INITIALIZING; 00171 00172 return STATUS_SUCCESS; 00173 } 00174 00175 static NTSTATUS NTAPI 00176 PciIdeXUdmaModesSupported( 00177 IN IDENTIFY_DATA IdentifyData, 00178 OUT PULONG BestXferMode, 00179 OUT PULONG CurrentXferMode) 00180 { 00181 ULONG Best = PIO_MODE0; 00182 ULONG Current = PIO_MODE0; 00183 00184 DPRINT("PciIdeXUdmaModesSupported(%lu, %p %p)\n", 00185 IdentifyData, BestXferMode, CurrentXferMode); 00186 00187 /* FIXME: if current mode is a PIO mode, how to get it? 00188 * At the moment, PIO_MODE0 is always returned... 00189 */ 00190 00191 if (IdentifyData.TranslationFieldsValid & 0x2) 00192 { 00193 /* PIO modes and some DMA modes are supported */ 00194 if (IdentifyData.AdvancedPIOModes & 0x10) 00195 Best = PIO_MODE4; 00196 else if (IdentifyData.AdvancedPIOModes & 0x8) 00197 Best = PIO_MODE3; 00198 else if (IdentifyData.AdvancedPIOModes & 0x4) 00199 Best = PIO_MODE2; 00200 else if (IdentifyData.AdvancedPIOModes & 0x2) 00201 Best = PIO_MODE1; 00202 else if (IdentifyData.AdvancedPIOModes & 0x1) 00203 Best = PIO_MODE0; 00204 00205 if (IdentifyData.SingleWordDMASupport & 0x4) 00206 Best = SWDMA_MODE2; 00207 else if (IdentifyData.SingleWordDMASupport & 0x2) 00208 Best = SWDMA_MODE1; 00209 else if (IdentifyData.SingleWordDMASupport & 0x1) 00210 Best = SWDMA_MODE0; 00211 00212 if (IdentifyData.SingleWordDMAActive & 0x4) 00213 Current = SWDMA_MODE2; 00214 else if (IdentifyData.SingleWordDMAActive & 0x2) 00215 Current = SWDMA_MODE1; 00216 else if (IdentifyData.SingleWordDMAActive & 0x1) 00217 Current = SWDMA_MODE0; 00218 00219 if (IdentifyData.MultiWordDMASupport & 0x4) 00220 Best = MWDMA_MODE2; 00221 else if (IdentifyData.MultiWordDMASupport & 0x2) 00222 Best = MWDMA_MODE1; 00223 else if (IdentifyData.MultiWordDMASupport & 0x1) 00224 Best = MWDMA_MODE0; 00225 00226 if (IdentifyData.MultiWordDMAActive & 0x4) 00227 Current = MWDMA_MODE2; 00228 else if (IdentifyData.MultiWordDMAActive & 0x2) 00229 Current = MWDMA_MODE1; 00230 else if (IdentifyData.MultiWordDMAActive & 0x1) 00231 Current = MWDMA_MODE0; 00232 } 00233 00234 if (IdentifyData.TranslationFieldsValid & 0x4) 00235 { 00236 /* UDMA modes are supported */ 00237 if (IdentifyData.UltraDMAActive & 0x10) 00238 Current = UDMA_MODE4; 00239 else if (IdentifyData.UltraDMAActive & 0x8) 00240 Current = UDMA_MODE3; 00241 else if (IdentifyData.UltraDMAActive & 0x4) 00242 Current = UDMA_MODE2; 00243 else if (IdentifyData.UltraDMAActive & 0x2) 00244 Current = UDMA_MODE1; 00245 else if (IdentifyData.UltraDMAActive & 0x1) 00246 Current = UDMA_MODE0; 00247 00248 if (IdentifyData.UltraDMASupport & 0x10) 00249 Best = UDMA_MODE4; 00250 else if (IdentifyData.UltraDMASupport & 0x8) 00251 Best = UDMA_MODE3; 00252 else if (IdentifyData.UltraDMASupport & 0x4) 00253 Best = UDMA_MODE2; 00254 else if (IdentifyData.UltraDMASupport & 0x2) 00255 Best = UDMA_MODE1; 00256 else if (IdentifyData.UltraDMASupport & 0x1) 00257 Best = UDMA_MODE0; 00258 } 00259 00260 *BestXferMode = Best; 00261 *CurrentXferMode = Current; 00262 return TRUE; 00263 } 00264 00265 static NTSTATUS 00266 PciIdeXFdoStartDevice( 00267 IN PDEVICE_OBJECT DeviceObject, 00268 IN PIRP Irp) 00269 { 00270 PPCIIDEX_DRIVER_EXTENSION DriverExtension; 00271 PFDO_DEVICE_EXTENSION DeviceExtension; 00272 PCM_RESOURCE_LIST ResourceList; 00273 NTSTATUS Status; 00274 00275 DPRINT("PciIdeXStartDevice(%p %p)\n", DeviceObject, Irp); 00276 00277 DriverExtension = IoGetDriverObjectExtension(DeviceObject->DriverObject, DeviceObject->DriverObject); 00278 ASSERT(DriverExtension); 00279 DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 00280 ASSERT(DeviceExtension); 00281 ASSERT(DeviceExtension->Common.IsFDO); 00282 00283 DeviceExtension->Properties.Size = sizeof(IDE_CONTROLLER_PROPERTIES); 00284 DeviceExtension->Properties.ExtensionSize = DriverExtension->MiniControllerExtensionSize; 00285 Status = DriverExtension->HwGetControllerProperties( 00286 DeviceExtension->MiniControllerExtension, 00287 &DeviceExtension->Properties); 00288 if (!NT_SUCCESS(Status)) 00289 return Status; 00290 00291 DriverExtension->HwUdmaModesSupported = DeviceExtension->Properties.PciIdeUdmaModesSupported; 00292 if (!DriverExtension->HwUdmaModesSupported) 00293 /* This method is optional, so provide our own one */ 00294 DriverExtension->HwUdmaModesSupported = PciIdeXUdmaModesSupported; 00295 00296 /* Get bus master port base, if any */ 00297 ResourceList = IoGetCurrentIrpStackLocation(Irp)->Parameters.StartDevice.AllocatedResources; 00298 if (ResourceList 00299 && ResourceList->Count == 1 00300 && ResourceList->List[0].PartialResourceList.Count == 1 00301 && ResourceList->List[0].PartialResourceList.Version == 1 00302 && ResourceList->List[0].PartialResourceList.Revision == 1 00303 && ResourceList->List[0].PartialResourceList.PartialDescriptors[0].Type == CmResourceTypePort 00304 && ResourceList->List[0].PartialResourceList.PartialDescriptors[0].u.Port.Length == 16) 00305 { 00306 DeviceExtension->BusMasterPortBase = ResourceList->List[0].PartialResourceList.PartialDescriptors[0].u.Port.Start; 00307 } 00308 return STATUS_SUCCESS; 00309 } 00310 00311 static NTSTATUS 00312 PciIdeXFdoQueryBusRelations( 00313 IN PDEVICE_OBJECT DeviceObject, 00314 OUT PDEVICE_RELATIONS* pDeviceRelations) 00315 { 00316 PFDO_DEVICE_EXTENSION DeviceExtension; 00317 PDEVICE_RELATIONS DeviceRelations = NULL; 00318 PDEVICE_OBJECT Pdo; 00319 PPDO_DEVICE_EXTENSION PdoDeviceExtension; 00320 ULONG i, j; 00321 ULONG PDOs = 0; 00322 IDE_CHANNEL_STATE ChannelState; 00323 NTSTATUS Status; 00324 00325 DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 00326 ASSERT(DeviceExtension); 00327 ASSERT(DeviceExtension->Common.IsFDO); 00328 00329 for (i = 0; i < MAX_IDE_CHANNEL; i++) 00330 { 00331 if (DeviceExtension->Pdo[i]) 00332 { 00333 PDOs++; 00334 continue; 00335 } 00336 ChannelState = DeviceExtension->Properties.PciIdeChannelEnabled( 00337 DeviceExtension->MiniControllerExtension, i); 00338 if (ChannelState == ChannelDisabled) 00339 { 00340 DPRINT("Channel %lu is disabled\n", i); 00341 continue; 00342 } 00343 00344 /* Need to create a PDO */ 00345 Status = IoCreateDevice( 00346 DeviceObject->DriverObject, 00347 sizeof(PDO_DEVICE_EXTENSION), 00348 NULL, 00349 FILE_DEVICE_CONTROLLER, 00350 FILE_AUTOGENERATED_DEVICE_NAME, 00351 FALSE, 00352 &Pdo); 00353 if (!NT_SUCCESS(Status)) 00354 /* FIXME: handle error */ 00355 continue; 00356 00357 PdoDeviceExtension = (PPDO_DEVICE_EXTENSION)Pdo->DeviceExtension; 00358 RtlZeroMemory(PdoDeviceExtension, sizeof(PDO_DEVICE_EXTENSION)); 00359 PdoDeviceExtension->Common.IsFDO = FALSE; 00360 PdoDeviceExtension->Channel = i; 00361 PdoDeviceExtension->ControllerFdo = DeviceObject; 00362 Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE; 00363 Pdo->Flags &= ~DO_DEVICE_INITIALIZING; 00364 00365 DeviceExtension->Pdo[i] = Pdo; 00366 PDOs++; 00367 } 00368 00369 if (PDOs == 0) 00370 { 00371 DeviceRelations = (PDEVICE_RELATIONS)ExAllocatePool( 00372 PagedPool, 00373 sizeof(DEVICE_RELATIONS)); 00374 } 00375 else 00376 { 00377 DeviceRelations = (PDEVICE_RELATIONS)ExAllocatePool( 00378 PagedPool, 00379 sizeof(DEVICE_RELATIONS) + sizeof(PDEVICE_OBJECT) * (PDOs - 1)); 00380 } 00381 if (!DeviceRelations) 00382 return STATUS_INSUFFICIENT_RESOURCES; 00383 00384 DeviceRelations->Count = PDOs; 00385 for (i = 0, j = 0; i < MAX_IDE_CHANNEL; i++) 00386 { 00387 if (DeviceExtension->Pdo[i]) 00388 { 00389 ObReferenceObject(DeviceExtension->Pdo[i]); 00390 DeviceRelations->Objects[j++] = DeviceExtension->Pdo[i]; 00391 } 00392 } 00393 00394 *pDeviceRelations = DeviceRelations; 00395 return STATUS_SUCCESS; 00396 } 00397 00398 NTSTATUS NTAPI 00399 PciIdeXFdoPnpDispatch( 00400 IN PDEVICE_OBJECT DeviceObject, 00401 IN PIRP Irp) 00402 { 00403 ULONG MinorFunction; 00404 PIO_STACK_LOCATION Stack; 00405 ULONG_PTR Information = Irp->IoStatus.Information; 00406 NTSTATUS Status; 00407 00408 Stack = IoGetCurrentIrpStackLocation(Irp); 00409 MinorFunction = Stack->MinorFunction; 00410 00411 switch (MinorFunction) 00412 { 00413 case IRP_MN_START_DEVICE: /* 0x00 */ 00414 { 00415 DPRINT("IRP_MJ_PNP / IRP_MN_START_DEVICE\n"); 00416 /* Call lower driver */ 00417 Status = ForwardIrpAndWait(DeviceObject, Irp); 00418 if (NT_SUCCESS(Status)) 00419 Status = PciIdeXFdoStartDevice(DeviceObject, Irp); 00420 break; 00421 } 00422 case IRP_MN_QUERY_REMOVE_DEVICE: /* 0x01 */ 00423 { 00424 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_REMOVE_DEVICE\n"); 00425 Status = STATUS_UNSUCCESSFUL; 00426 break; 00427 } 00428 case IRP_MN_QUERY_DEVICE_RELATIONS: /* 0x07 */ 00429 { 00430 switch (Stack->Parameters.QueryDeviceRelations.Type) 00431 { 00432 case BusRelations: 00433 { 00434 PDEVICE_RELATIONS DeviceRelations = NULL; 00435 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n"); 00436 Status = PciIdeXFdoQueryBusRelations(DeviceObject, &DeviceRelations); 00437 Information = (ULONG_PTR)DeviceRelations; 00438 break; 00439 } 00440 default: 00441 { 00442 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n", 00443 Stack->Parameters.QueryDeviceRelations.Type); 00444 Status = STATUS_NOT_IMPLEMENTED; 00445 break; 00446 } 00447 } 00448 break; 00449 } 00450 case IRP_MN_QUERY_PNP_DEVICE_STATE: /* 0x14 */ 00451 { 00452 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_PNP_DEVICE_STATE\n"); 00453 Information |= PNP_DEVICE_NOT_DISABLEABLE; 00454 Status = STATUS_SUCCESS; 00455 break; 00456 } 00457 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS: /* 0x0d */ 00458 { 00459 DPRINT("IRP_MJ_PNP / IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n"); 00460 return ForwardIrpAndForget(DeviceObject, Irp); 00461 } 00462 default: 00463 { 00464 DPRINT1("IRP_MJ_PNP / Unknown minor function 0x%lx\n", MinorFunction); 00465 return ForwardIrpAndForget(DeviceObject, Irp); 00466 } 00467 } 00468 00469 Irp->IoStatus.Information = Information; 00470 Irp->IoStatus.Status = Status; 00471 IoCompleteRequest(Irp, IO_NO_INCREMENT); 00472 return Status; 00473 } Generated on Sat May 26 2012 04:26:01 for ReactOS by
1.7.6.1
|