ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

fdo.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.