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

pdo.c
Go to the documentation of this file.
00001 /*
00002  * PROJECT:         ReactOS PCI bus driver
00003  * FILE:            pdo.c
00004  * PURPOSE:         Child device object dispatch routines
00005  * PROGRAMMERS:     Casper S. Hornstrup (chorns@users.sourceforge.net)
00006  * UPDATE HISTORY:
00007  *      10-09-2001  CSH  Created
00008  */
00009 
00010 #include "pci.h"
00011 
00012 #ifndef NDEBUG
00013 #define NDEBUG
00014 #endif
00015 #include <debug.h>
00016 
00017 /*** PRIVATE *****************************************************************/
00018 
00019 static NTSTATUS
00020 PdoQueryDeviceText(
00021   IN PDEVICE_OBJECT DeviceObject,
00022   IN PIRP Irp,
00023   PIO_STACK_LOCATION IrpSp)
00024 {
00025   PPDO_DEVICE_EXTENSION DeviceExtension;
00026   UNICODE_STRING String;
00027   NTSTATUS Status;
00028 
00029   DPRINT("Called\n");
00030 
00031   DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
00032 
00033   switch (IrpSp->Parameters.QueryDeviceText.DeviceTextType)
00034   {
00035     case DeviceTextDescription:
00036       Status = PciDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
00037                                          &DeviceExtension->DeviceDescription,
00038                                          &String);
00039 
00040       DPRINT("DeviceTextDescription\n");
00041       Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
00042       break;
00043 
00044     case DeviceTextLocationInformation:
00045       Status = PciDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
00046                                          &DeviceExtension->DeviceLocation,
00047                                          &String);
00048 
00049       DPRINT("DeviceTextLocationInformation\n");
00050       Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
00051       break;
00052 
00053     default:
00054       Irp->IoStatus.Information = 0;
00055       Status = STATUS_INVALID_PARAMETER;
00056       break;
00057   }
00058 
00059   return Status;
00060 }
00061 
00062 
00063 static NTSTATUS
00064 PdoQueryId(
00065   IN PDEVICE_OBJECT DeviceObject,
00066   IN PIRP Irp,
00067   PIO_STACK_LOCATION IrpSp)
00068 {
00069   PPDO_DEVICE_EXTENSION DeviceExtension;
00070   UNICODE_STRING String;
00071   NTSTATUS Status;
00072 
00073   DPRINT("Called\n");
00074 
00075   DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
00076 
00077 //  Irp->IoStatus.Information = 0;
00078 
00079   Status = STATUS_SUCCESS;
00080 
00081   RtlInitUnicodeString(&String, NULL);
00082 
00083   switch (IrpSp->Parameters.QueryId.IdType) {
00084     case BusQueryDeviceID:
00085       Status = PciDuplicateUnicodeString(
00086         RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
00087         &DeviceExtension->DeviceID,
00088         &String);
00089 
00090       DPRINT("DeviceID: %S\n", String.Buffer);
00091 
00092       Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
00093       break;
00094 
00095     case BusQueryHardwareIDs:
00096       Status = PciDuplicateUnicodeString(
00097         RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
00098         &DeviceExtension->HardwareIDs,
00099         &String);
00100 
00101       Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
00102       break;
00103 
00104     case BusQueryCompatibleIDs:
00105       Status = PciDuplicateUnicodeString(
00106         RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
00107         &DeviceExtension->CompatibleIDs,
00108         &String);
00109 
00110       Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
00111       break;
00112 
00113     case BusQueryInstanceID:
00114       Status = PciDuplicateUnicodeString(
00115         RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
00116         &DeviceExtension->InstanceID,
00117         &String);
00118 
00119       DPRINT("InstanceID: %S\n", String.Buffer);
00120 
00121       Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
00122       break;
00123 
00124     case BusQueryDeviceSerialNumber:
00125     default:
00126       Status = STATUS_NOT_IMPLEMENTED;
00127   }
00128 
00129   return Status;
00130 }
00131 
00132 
00133 static NTSTATUS
00134 PdoQueryBusInformation(
00135   IN PDEVICE_OBJECT DeviceObject,
00136   IN PIRP Irp,
00137   PIO_STACK_LOCATION IrpSp)
00138 {
00139   PPDO_DEVICE_EXTENSION DeviceExtension;
00140   PPNP_BUS_INFORMATION BusInformation;
00141 
00142   UNREFERENCED_PARAMETER(IrpSp);
00143   DPRINT("Called\n");
00144 
00145   DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
00146   BusInformation = ExAllocatePool(PagedPool, sizeof(PNP_BUS_INFORMATION));
00147   Irp->IoStatus.Information = (ULONG_PTR)BusInformation;
00148   if (BusInformation != NULL)
00149   {
00150     BusInformation->BusTypeGuid = GUID_BUS_TYPE_PCI;
00151     BusInformation->LegacyBusType = PCIBus;
00152     BusInformation->BusNumber = DeviceExtension->PciDevice->BusNumber;
00153 
00154     return STATUS_SUCCESS;
00155   }
00156 
00157   return STATUS_INSUFFICIENT_RESOURCES;
00158 }
00159 
00160 
00161 static NTSTATUS
00162 PdoQueryCapabilities(
00163   IN PDEVICE_OBJECT DeviceObject,
00164   IN PIRP Irp,
00165   PIO_STACK_LOCATION IrpSp)
00166 {
00167   PPDO_DEVICE_EXTENSION DeviceExtension;
00168   PDEVICE_CAPABILITIES DeviceCapabilities;
00169   ULONG DeviceNumber, FunctionNumber;
00170 
00171   UNREFERENCED_PARAMETER(Irp);
00172   DPRINT("Called\n");
00173 
00174   DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
00175   DeviceCapabilities = IrpSp->Parameters.DeviceCapabilities.Capabilities;
00176 
00177   if (DeviceCapabilities->Version != 1)
00178     return STATUS_UNSUCCESSFUL;
00179 
00180   DeviceNumber = DeviceExtension->PciDevice->SlotNumber.u.bits.DeviceNumber;
00181   FunctionNumber = DeviceExtension->PciDevice->SlotNumber.u.bits.FunctionNumber;
00182 
00183   DeviceCapabilities->UniqueID = FALSE;
00184   DeviceCapabilities->Address = ((DeviceNumber << 16) & 0xFFFF0000) + (FunctionNumber & 0xFFFF);
00185   DeviceCapabilities->UINumber = MAXULONG; /* FIXME */
00186 
00187   return STATUS_SUCCESS;
00188 }
00189 
00190 
00191 static BOOLEAN
00192 PdoGetRangeLength(PPDO_DEVICE_EXTENSION DeviceExtension,
00193                   ULONG Offset,
00194                   PULONG Base,
00195                   PULONG Length,
00196                   PULONG Flags)
00197 {
00198   ULONG OrigValue;
00199   ULONG BaseValue;
00200   ULONG NewValue;
00201   ULONG Size;
00202   ULONG XLength;
00203 
00204   /* Save original value */
00205   Size= HalGetBusDataByOffset(PCIConfiguration,
00206                               DeviceExtension->PciDevice->BusNumber,
00207                               DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
00208                               &OrigValue,
00209                               Offset,
00210                               sizeof(ULONG));
00211   if (Size != sizeof(ULONG))
00212   {
00213     DPRINT1("Wrong size %lu\n", Size);
00214     return FALSE;
00215   }
00216 
00217   BaseValue = (OrigValue & PCI_ADDRESS_IO_SPACE)
00218               ? (OrigValue & PCI_ADDRESS_IO_ADDRESS_MASK)
00219               : (OrigValue & PCI_ADDRESS_MEMORY_ADDRESS_MASK);
00220 
00221   *Base = BaseValue;
00222 
00223   /* Set magic value */
00224   NewValue = MAXULONG;
00225   Size= HalSetBusDataByOffset(PCIConfiguration,
00226                               DeviceExtension->PciDevice->BusNumber,
00227                               DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
00228                               &NewValue,
00229                               Offset,
00230                               sizeof(ULONG));
00231   if (Size != sizeof(ULONG))
00232   {
00233     DPRINT1("Wrong size %lu\n", Size);
00234     return FALSE;
00235   }
00236 
00237   /* Get the range length */
00238   Size= HalGetBusDataByOffset(PCIConfiguration,
00239                               DeviceExtension->PciDevice->BusNumber,
00240                               DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
00241                               &NewValue,
00242                               Offset,
00243                               sizeof(ULONG));
00244   if (Size != sizeof(ULONG))
00245   {
00246     DPRINT1("Wrong size %lu\n", Size);
00247     return FALSE;
00248   }
00249 
00250   /* Restore original value */
00251   Size= HalSetBusDataByOffset(PCIConfiguration,
00252                               DeviceExtension->PciDevice->BusNumber,
00253                               DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
00254                               &OrigValue,
00255                               Offset,
00256                               sizeof(ULONG));
00257   if (Size != sizeof(ULONG))
00258   {
00259     DPRINT1("Wrong size %lu\n", Size);
00260     return FALSE;
00261   }
00262 
00263   if (NewValue == 0)
00264   {
00265     DPRINT("Unused address register\n");
00266     *Base = 0;
00267     *Length = 0;
00268     *Flags = 0;
00269      return TRUE;
00270   }
00271 
00272   XLength = ~((NewValue & PCI_ADDRESS_IO_SPACE)
00273               ? (NewValue & PCI_ADDRESS_IO_ADDRESS_MASK)
00274               : (NewValue & PCI_ADDRESS_MEMORY_ADDRESS_MASK)) + 1;
00275 
00276 #if 0
00277   DbgPrint("BaseAddress 0x%08lx  Length 0x%08lx",
00278            BaseValue, XLength);
00279 
00280   if (NewValue & PCI_ADDRESS_IO_SPACE)
00281   {
00282     DbgPrint("  IO range");
00283   }
00284   else
00285   {
00286     DbgPrint("  Memory range");
00287     if ((NewValue & PCI_ADDRESS_MEMORY_TYPE_MASK) == 0)
00288     {
00289       DbgPrint(" in 32-Bit address space");
00290     }
00291     else if ((NewValue & PCI_ADDRESS_MEMORY_TYPE_MASK) == 2)
00292     {
00293       DbgPrint(" below 1BM ");
00294     }
00295     else if ((NewValue & PCI_ADDRESS_MEMORY_TYPE_MASK) == 4)
00296     {
00297       DbgPrint(" in 64-Bit address space");
00298     }
00299 
00300     if (NewValue & PCI_ADDRESS_MEMORY_PREFETCHABLE)
00301     {
00302       DbgPrint(" prefetchable");
00303     }
00304   }
00305 
00306   DbgPrint("\n");
00307 #endif
00308 
00309   *Length = XLength;
00310   *Flags = (NewValue & PCI_ADDRESS_IO_SPACE)
00311            ? (NewValue & ~PCI_ADDRESS_IO_ADDRESS_MASK)
00312            : (NewValue & ~PCI_ADDRESS_MEMORY_ADDRESS_MASK);
00313 
00314   return TRUE;
00315 }
00316 
00317 
00318 static NTSTATUS
00319 PdoQueryResourceRequirements(
00320   IN PDEVICE_OBJECT DeviceObject,
00321   IN PIRP Irp,
00322   PIO_STACK_LOCATION IrpSp)
00323 {
00324   PPDO_DEVICE_EXTENSION DeviceExtension;
00325   PCI_COMMON_CONFIG PciConfig;
00326   PIO_RESOURCE_REQUIREMENTS_LIST ResourceList;
00327   PIO_RESOURCE_DESCRIPTOR Descriptor;
00328   ULONG Size;
00329   ULONG ResCount = 0;
00330   ULONG ListSize;
00331   ULONG i;
00332   ULONG Base;
00333   ULONG Length;
00334   ULONG Flags;
00335 
00336   UNREFERENCED_PARAMETER(IrpSp);
00337   DPRINT("PdoQueryResourceRequirements() called\n");
00338 
00339   DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
00340 
00341   /* Get PCI configuration space */
00342   Size= HalGetBusData(PCIConfiguration,
00343                       DeviceExtension->PciDevice->BusNumber,
00344                       DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
00345                       &PciConfig,
00346                       PCI_COMMON_HDR_LENGTH);
00347   DPRINT("Size %lu\n", Size);
00348   if (Size < PCI_COMMON_HDR_LENGTH)
00349   {
00350     Irp->IoStatus.Information = 0;
00351     return STATUS_UNSUCCESSFUL;
00352   }
00353 
00354   DPRINT("Command register: 0x%04hx\n", PciConfig.Command);
00355 
00356   /* Count required resource descriptors */
00357   ResCount = 0;
00358   if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_DEVICE_TYPE)
00359   {
00360     for (i = 0; i < PCI_TYPE0_ADDRESSES; i++)
00361     {
00362       if (!PdoGetRangeLength(DeviceExtension,
00363                  0x10 + i * 4,
00364                  &Base,
00365                  &Length,
00366                  &Flags))
00367     break;
00368 
00369       if (Length != 0)
00370         ResCount += 2;
00371     }
00372 
00373     /* FIXME: Check ROM address */
00374 
00375     if (PciConfig.u.type0.InterruptPin != 0)
00376       ResCount++;
00377   }
00378   else if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_BRIDGE_TYPE)
00379   {
00380     for (i = 0; i < PCI_TYPE1_ADDRESSES; i++)
00381     {
00382       if (!PdoGetRangeLength(DeviceExtension,
00383                  0x10 + i * 4,
00384                  &Base,
00385                  &Length,
00386                  &Flags))
00387     break;
00388 
00389       if (Length != 0)
00390         ResCount += 2;
00391     }
00392     if (DeviceExtension->PciDevice->PciConfig.BaseClass == PCI_CLASS_BRIDGE_DEV)
00393       ResCount++;
00394   }
00395   else if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_CARDBUS_BRIDGE_TYPE)
00396   {
00397     /* FIXME: Count Cardbus bridge resources */
00398   }
00399   else
00400   {
00401     DPRINT1("Unsupported header type %u\n", PCI_CONFIGURATION_TYPE(&PciConfig));
00402   }
00403 
00404   if (ResCount == 0)
00405   {
00406     Irp->IoStatus.Information = 0;
00407     return STATUS_SUCCESS;
00408   }
00409 
00410   /* Calculate the resource list size */
00411   ListSize = FIELD_OFFSET(IO_RESOURCE_REQUIREMENTS_LIST, List[0].Descriptors)
00412     + ResCount * sizeof(IO_RESOURCE_DESCRIPTOR);
00413 
00414   DPRINT("ListSize %lu (0x%lx)\n", ListSize, ListSize);
00415 
00416   /* Allocate the resource requirements list */
00417   ResourceList = ExAllocatePoolWithTag(PagedPool,
00418                                 ListSize, TAG_PCI);
00419   if (ResourceList == NULL)
00420   {
00421     Irp->IoStatus.Information = 0;
00422     return STATUS_INSUFFICIENT_RESOURCES;
00423   }
00424 
00425   RtlZeroMemory(ResourceList, ListSize);
00426   ResourceList->ListSize = ListSize;
00427   ResourceList->InterfaceType = PCIBus;
00428   ResourceList->BusNumber = DeviceExtension->PciDevice->BusNumber;
00429   ResourceList->SlotNumber = DeviceExtension->PciDevice->SlotNumber.u.AsULONG;
00430   ResourceList->AlternativeLists = 1;
00431 
00432   ResourceList->List[0].Version = 1;
00433   ResourceList->List[0].Revision = 1;
00434   ResourceList->List[0].Count = ResCount;
00435 
00436   Descriptor = &ResourceList->List[0].Descriptors[0];
00437   if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_DEVICE_TYPE)
00438   {
00439     for (i = 0; i < PCI_TYPE0_ADDRESSES; i++)
00440     {
00441       if (!PdoGetRangeLength(DeviceExtension,
00442                  0x10 + i * 4,
00443                  &Base,
00444                  &Length,
00445                  &Flags))
00446       {
00447         DPRINT1("PdoGetRangeLength() failed\n");
00448         break;
00449       }
00450 
00451       if (Length == 0)
00452       {
00453         DPRINT("Unused address register\n");
00454         continue;
00455       }
00456 
00457       /* Set preferred descriptor */
00458       Descriptor->Option = IO_RESOURCE_PREFERRED;
00459       if (Flags & PCI_ADDRESS_IO_SPACE)
00460       {
00461         Descriptor->Type = CmResourceTypePort;
00462         Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
00463         Descriptor->Flags = CM_RESOURCE_PORT_IO |
00464                             CM_RESOURCE_PORT_16_BIT_DECODE |
00465                             CM_RESOURCE_PORT_POSITIVE_DECODE;
00466 
00467         Descriptor->u.Port.Length = Length;
00468         Descriptor->u.Port.Alignment = 1;
00469         Descriptor->u.Port.MinimumAddress.QuadPart = (ULONGLONG)Base;
00470         Descriptor->u.Port.MaximumAddress.QuadPart = (ULONGLONG)(Base + Length - 1);
00471       }
00472       else
00473       {
00474         Descriptor->Type = CmResourceTypeMemory;
00475         Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
00476         Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
00477 
00478         Descriptor->u.Memory.Length = Length;
00479         Descriptor->u.Memory.Alignment = 1;
00480         Descriptor->u.Memory.MinimumAddress.QuadPart = (ULONGLONG)Base;
00481         Descriptor->u.Memory.MaximumAddress.QuadPart = (ULONGLONG)(Base + Length - 1);
00482       }
00483       Descriptor++;
00484 
00485       /* Set alternative descriptor */
00486       Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
00487       if (Flags & PCI_ADDRESS_IO_SPACE)
00488       {
00489         Descriptor->Type = CmResourceTypePort;
00490         Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
00491         Descriptor->Flags = CM_RESOURCE_PORT_IO |
00492                             CM_RESOURCE_PORT_16_BIT_DECODE |
00493                             CM_RESOURCE_PORT_POSITIVE_DECODE;
00494 
00495         Descriptor->u.Port.Length = Length;
00496         Descriptor->u.Port.Alignment = Length;
00497         Descriptor->u.Port.MinimumAddress.QuadPart = (ULONGLONG)0;
00498         Descriptor->u.Port.MaximumAddress.QuadPart = (ULONGLONG)0x00000000FFFFFFFF;
00499       }
00500       else
00501       {
00502         Descriptor->Type = CmResourceTypeMemory;
00503         Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
00504         Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
00505 
00506         Descriptor->u.Memory.Length = Length;
00507         Descriptor->u.Memory.Alignment = Length;
00508         Descriptor->u.Port.MinimumAddress.QuadPart = (ULONGLONG)0;
00509         Descriptor->u.Port.MaximumAddress.QuadPart = (ULONGLONG)0x00000000FFFFFFFF;
00510       }
00511       Descriptor++;
00512     }
00513 
00514     /* FIXME: Check ROM address */
00515 
00516     if (PciConfig.u.type0.InterruptPin != 0)
00517     {
00518       Descriptor->Option = 0; /* Required */
00519       Descriptor->Type = CmResourceTypeInterrupt;
00520       Descriptor->ShareDisposition = CmResourceShareShared;
00521       Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
00522 
00523       Descriptor->u.Interrupt.MinimumVector = 0;
00524       Descriptor->u.Interrupt.MaximumVector = 0xFF;
00525     }
00526   }
00527   else if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_BRIDGE_TYPE)
00528   {
00529     for (i = 0; i < PCI_TYPE1_ADDRESSES; i++)
00530     {
00531       if (!PdoGetRangeLength(DeviceExtension,
00532                  0x10 + i * 4,
00533                  &Base,
00534                  &Length,
00535                  &Flags))
00536       {
00537         DPRINT1("PdoGetRangeLength() failed\n");
00538         break;
00539       }
00540 
00541       if (Length == 0)
00542       {
00543         DPRINT("Unused address register\n");
00544         continue;
00545       }
00546 
00547       /* Set preferred descriptor */
00548       Descriptor->Option = IO_RESOURCE_PREFERRED;
00549       if (Flags & PCI_ADDRESS_IO_SPACE)
00550       {
00551         Descriptor->Type = CmResourceTypePort;
00552         Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
00553         Descriptor->Flags = CM_RESOURCE_PORT_IO |
00554                             CM_RESOURCE_PORT_16_BIT_DECODE |
00555                             CM_RESOURCE_PORT_POSITIVE_DECODE;
00556 
00557         Descriptor->u.Port.Length = Length;
00558         Descriptor->u.Port.Alignment = 1;
00559         Descriptor->u.Port.MinimumAddress.QuadPart = (ULONGLONG)Base;
00560         Descriptor->u.Port.MaximumAddress.QuadPart = (ULONGLONG)(Base + Length - 1);
00561       }
00562       else
00563       {
00564         Descriptor->Type = CmResourceTypeMemory;
00565         Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
00566         Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
00567 
00568         Descriptor->u.Memory.Length = Length;
00569         Descriptor->u.Memory.Alignment = 1;
00570         Descriptor->u.Memory.MinimumAddress.QuadPart = (ULONGLONG)Base;
00571         Descriptor->u.Memory.MaximumAddress.QuadPart = (ULONGLONG)(Base + Length - 1);
00572       }
00573       Descriptor++;
00574 
00575       /* Set alternative descriptor */
00576       Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
00577       if (Flags & PCI_ADDRESS_IO_SPACE)
00578       {
00579         Descriptor->Type = CmResourceTypePort;
00580         Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
00581         Descriptor->Flags = CM_RESOURCE_PORT_IO |
00582                             CM_RESOURCE_PORT_16_BIT_DECODE |
00583                             CM_RESOURCE_PORT_POSITIVE_DECODE;
00584 
00585         Descriptor->u.Port.Length = Length;
00586         Descriptor->u.Port.Alignment = Length;
00587         Descriptor->u.Port.MinimumAddress.QuadPart = (ULONGLONG)0;
00588         Descriptor->u.Port.MaximumAddress.QuadPart = (ULONGLONG)0x00000000FFFFFFFF;
00589       }
00590       else
00591       {
00592         Descriptor->Type = CmResourceTypeMemory;
00593         Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
00594         Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
00595 
00596         Descriptor->u.Memory.Length = Length;
00597         Descriptor->u.Memory.Alignment = Length;
00598         Descriptor->u.Port.MinimumAddress.QuadPart = (ULONGLONG)0;
00599         Descriptor->u.Port.MaximumAddress.QuadPart = (ULONGLONG)0x00000000FFFFFFFF;
00600       }
00601       Descriptor++;
00602     }
00603     if (DeviceExtension->PciDevice->PciConfig.BaseClass == PCI_CLASS_BRIDGE_DEV)
00604     {
00605       Descriptor->Option = 0; /* Required */
00606       Descriptor->Type = CmResourceTypeBusNumber;
00607       Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
00608 
00609       ResourceList->BusNumber =
00610       Descriptor->u.BusNumber.MinBusNumber =
00611       Descriptor->u.BusNumber.MaxBusNumber = DeviceExtension->PciDevice->PciConfig.u.type1.SecondaryBus;
00612       Descriptor->u.BusNumber.Length = 1;
00613       Descriptor->u.BusNumber.Reserved = 0;
00614     }
00615   }
00616   else if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_CARDBUS_BRIDGE_TYPE)
00617   {
00618     /* FIXME: Add Cardbus bridge resources */
00619   }
00620 
00621   Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
00622 
00623   return STATUS_SUCCESS;
00624 }
00625 
00626 
00627 static NTSTATUS
00628 PdoQueryResources(
00629   IN PDEVICE_OBJECT DeviceObject,
00630   IN PIRP Irp,
00631   PIO_STACK_LOCATION IrpSp)
00632 {
00633   PPDO_DEVICE_EXTENSION DeviceExtension;
00634   PCI_COMMON_CONFIG PciConfig;
00635   PCM_RESOURCE_LIST ResourceList;
00636   PCM_PARTIAL_RESOURCE_LIST PartialList;
00637   PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
00638   ULONG Size;
00639   ULONG ResCount = 0;
00640   ULONG ListSize;
00641   ULONG i;
00642   ULONG Base;
00643   ULONG Length;
00644   ULONG Flags;
00645 
00646   DPRINT("PdoQueryResources() called\n");
00647 
00648   UNREFERENCED_PARAMETER(IrpSp);
00649   DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
00650 
00651   /* Get PCI configuration space */
00652   Size= HalGetBusData(PCIConfiguration,
00653                       DeviceExtension->PciDevice->BusNumber,
00654                       DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
00655                       &PciConfig,
00656                       PCI_COMMON_HDR_LENGTH);
00657   DPRINT("Size %lu\n", Size);
00658   if (Size < PCI_COMMON_HDR_LENGTH)
00659   {
00660     Irp->IoStatus.Information = 0;
00661     return STATUS_UNSUCCESSFUL;
00662   }
00663 
00664   DPRINT("Command register: 0x%04hx\n", PciConfig.Command);
00665 
00666   /* Count required resource descriptors */
00667   ResCount = 0;
00668   if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_DEVICE_TYPE)
00669   {
00670     for (i = 0; i < PCI_TYPE0_ADDRESSES; i++)
00671     {
00672       if (!PdoGetRangeLength(DeviceExtension,
00673                  0x10 + i * 4,
00674                  &Base,
00675                  &Length,
00676                  &Flags))
00677         break;
00678 
00679       if (Length)
00680         ResCount++;
00681     }
00682 
00683     if ((PciConfig.u.type0.InterruptPin != 0) &&
00684         (PciConfig.u.type0.InterruptLine != 0) &&
00685         (PciConfig.u.type0.InterruptLine != 0xFF))
00686       ResCount++;
00687   }
00688   else if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_BRIDGE_TYPE)
00689   {
00690     for (i = 0; i < PCI_TYPE1_ADDRESSES; i++)
00691     {
00692       if (!PdoGetRangeLength(DeviceExtension,
00693                  0x10 + i * 4,
00694                  &Base,
00695                  &Length,
00696                  &Flags))
00697         break;
00698 
00699       if (Length != 0)
00700         ResCount++;
00701     }
00702     if (DeviceExtension->PciDevice->PciConfig.BaseClass == PCI_CLASS_BRIDGE_DEV)
00703       ResCount++;
00704   }
00705   else if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_CARDBUS_BRIDGE_TYPE)
00706   {
00707     /* FIXME: Count Cardbus bridge resources */
00708   }
00709   else
00710   {
00711     DPRINT1("Unsupported header type %u\n", PCI_CONFIGURATION_TYPE(&PciConfig));
00712   }
00713 
00714   if (ResCount == 0)
00715   {
00716     Irp->IoStatus.Information = 0;
00717     return STATUS_SUCCESS;
00718   }
00719 
00720   /* Calculate the resource list size */
00721   ListSize = FIELD_OFFSET(CM_RESOURCE_LIST, List[0].PartialResourceList.PartialDescriptors)
00722     + ResCount * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
00723 
00724   /* Allocate the resource list */
00725   ResourceList = ExAllocatePoolWithTag(PagedPool,
00726                                 ListSize, TAG_PCI);
00727   if (ResourceList == NULL)
00728     return STATUS_INSUFFICIENT_RESOURCES;
00729 
00730   RtlZeroMemory(ResourceList, ListSize);
00731   ResourceList->Count = 1;
00732   ResourceList->List[0].InterfaceType = PCIBus;
00733   ResourceList->List[0].BusNumber = DeviceExtension->PciDevice->BusNumber;
00734 
00735   PartialList = &ResourceList->List[0].PartialResourceList;
00736   PartialList->Version = 1;
00737   PartialList->Revision = 1;
00738   PartialList->Count = ResCount;
00739 
00740   Descriptor = &PartialList->PartialDescriptors[0];
00741   if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_DEVICE_TYPE)
00742   {
00743     for (i = 0; i < PCI_TYPE0_ADDRESSES; i++)
00744     {
00745       if (!PdoGetRangeLength(DeviceExtension,
00746                  0x10 + i * 4,
00747                  &Base,
00748                  &Length,
00749                  &Flags))
00750       {
00751         DPRINT1("PdoGetRangeLength() failed\n");
00752         break;
00753       }
00754 
00755       if (Length == 0)
00756       {
00757         DPRINT("Unused address register\n");
00758         continue;
00759       }
00760 
00761       if (Flags & PCI_ADDRESS_IO_SPACE)
00762       {
00763         Descriptor->Type = CmResourceTypePort;
00764         Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
00765         Descriptor->Flags = CM_RESOURCE_PORT_IO;
00766         Descriptor->u.Port.Start.QuadPart =
00767           (ULONGLONG)Base;
00768         Descriptor->u.Port.Length = Length;
00769 
00770         /* Enable IO space access */
00771         DeviceExtension->PciDevice->EnableIoSpace = TRUE;
00772       }
00773       else
00774       {
00775         Descriptor->Type = CmResourceTypeMemory;
00776         Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
00777         Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
00778         Descriptor->u.Memory.Start.QuadPart =
00779           (ULONGLONG)Base;
00780         Descriptor->u.Memory.Length = Length;
00781 
00782         /* Enable memory space access */
00783         DeviceExtension->PciDevice->EnableMemorySpace = TRUE;
00784       }
00785 
00786       Descriptor++;
00787     }
00788 
00789     /* Add interrupt resource */
00790     if ((PciConfig.u.type0.InterruptPin != 0) &&
00791         (PciConfig.u.type0.InterruptLine != 0) &&
00792         (PciConfig.u.type0.InterruptLine != 0xFF))
00793     {
00794       Descriptor->Type = CmResourceTypeInterrupt;
00795       Descriptor->ShareDisposition = CmResourceShareShared;
00796       Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
00797       Descriptor->u.Interrupt.Level = PciConfig.u.type0.InterruptLine;
00798       Descriptor->u.Interrupt.Vector = PciConfig.u.type0.InterruptLine;
00799       Descriptor->u.Interrupt.Affinity = 0xFFFFFFFF;
00800     }
00801 
00802     /* Allow bus master mode */
00803     DeviceExtension->PciDevice->EnableBusMaster = TRUE;
00804   }
00805   else if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_BRIDGE_TYPE)
00806   {
00807     for (i = 0; i < PCI_TYPE1_ADDRESSES; i++)
00808     {
00809       if (!PdoGetRangeLength(DeviceExtension,
00810                  0x10 + i * 4,
00811                  &Base,
00812                  &Length,
00813                  &Flags))
00814       {
00815         DPRINT1("PdoGetRangeLength() failed\n");
00816         break;
00817       }
00818 
00819       if (Length == 0)
00820       {
00821         DPRINT("Unused address register\n");
00822         continue;
00823       }
00824 
00825       if (Flags & PCI_ADDRESS_IO_SPACE)
00826       {
00827         Descriptor->Type = CmResourceTypePort;
00828         Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
00829         Descriptor->Flags = CM_RESOURCE_PORT_IO;
00830         Descriptor->u.Port.Start.QuadPart =
00831           (ULONGLONG)Base;
00832         Descriptor->u.Port.Length = Length;
00833 
00834         /* Enable IO space access */
00835         DeviceExtension->PciDevice->EnableIoSpace = TRUE;
00836       }
00837       else
00838       {
00839         Descriptor->Type = CmResourceTypeMemory;
00840         Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
00841         Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
00842         Descriptor->u.Memory.Start.QuadPart =
00843           (ULONGLONG)Base;
00844         Descriptor->u.Memory.Length = Length;
00845 
00846         /* Enable memory space access */
00847         DeviceExtension->PciDevice->EnableMemorySpace = TRUE;
00848       }
00849 
00850       Descriptor++;
00851     }
00852     if (DeviceExtension->PciDevice->PciConfig.BaseClass == PCI_CLASS_BRIDGE_DEV)
00853     {
00854       Descriptor->Type = CmResourceTypeBusNumber;
00855       Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
00856 
00857       ResourceList->List[0].BusNumber =
00858       Descriptor->u.BusNumber.Start = DeviceExtension->PciDevice->PciConfig.u.type1.SecondaryBus;
00859       Descriptor->u.BusNumber.Length = 1;
00860       Descriptor->u.BusNumber.Reserved = 0;
00861     }
00862   }
00863   else if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_CARDBUS_BRIDGE_TYPE)
00864   {
00865     /* FIXME: Add Cardbus bridge resources */
00866   }
00867 
00868   Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
00869 
00870   return STATUS_SUCCESS;
00871 }
00872 
00873 
00874 static VOID NTAPI
00875 InterfaceReference(
00876   IN PVOID Context)
00877 {
00878   PPDO_DEVICE_EXTENSION DeviceExtension;
00879 
00880   DPRINT("InterfaceReference(%p)\n", Context);
00881 
00882   DeviceExtension = (PPDO_DEVICE_EXTENSION)((PDEVICE_OBJECT)Context)->DeviceExtension;
00883   InterlockedIncrement(&DeviceExtension->References);
00884 }
00885 
00886 
00887 static VOID NTAPI
00888 InterfaceDereference(
00889   IN PVOID Context)
00890 {
00891   PPDO_DEVICE_EXTENSION DeviceExtension;
00892 
00893   DPRINT("InterfaceDereference(%p)\n", Context);
00894 
00895   DeviceExtension = (PPDO_DEVICE_EXTENSION)((PDEVICE_OBJECT)Context)->DeviceExtension;
00896   InterlockedDecrement(&DeviceExtension->References);
00897 }
00898 
00899 
00900 static BOOLEAN NTAPI
00901 InterfaceBusTranslateBusAddress(
00902   IN PVOID Context,
00903   IN PHYSICAL_ADDRESS BusAddress,
00904   IN ULONG Length,
00905   IN OUT PULONG AddressSpace,
00906   OUT PPHYSICAL_ADDRESS TranslatedAddress)
00907 {
00908   PPDO_DEVICE_EXTENSION DeviceExtension;
00909 
00910   DPRINT("InterfaceBusTranslateBusAddress(%p %p 0x%lx %p %p)\n",
00911     Context, BusAddress, Length, AddressSpace, TranslatedAddress);
00912 
00913   DeviceExtension = (PPDO_DEVICE_EXTENSION)((PDEVICE_OBJECT)Context)->DeviceExtension;
00914 
00915   return HalTranslateBusAddress(
00916     PCIBus, DeviceExtension->PciDevice->BusNumber,
00917     BusAddress, AddressSpace, TranslatedAddress);
00918 }
00919 
00920 
00921 static PDMA_ADAPTER NTAPI
00922 InterfaceBusGetDmaAdapter(
00923   IN PVOID Context,
00924   IN PDEVICE_DESCRIPTION DeviceDescription,
00925   OUT PULONG NumberOfMapRegisters)
00926 {
00927   DPRINT("InterfaceBusGetDmaAdapter(%p %p %p)\n",
00928     Context, DeviceDescription, NumberOfMapRegisters);
00929   return (PDMA_ADAPTER)HalGetAdapter(DeviceDescription, NumberOfMapRegisters);
00930 }
00931 
00932 
00933 static ULONG NTAPI
00934 InterfaceBusSetBusData(
00935   IN PVOID Context,
00936   IN ULONG DataType,
00937   IN PVOID Buffer,
00938   IN ULONG Offset,
00939   IN ULONG Length)
00940 {
00941   PPDO_DEVICE_EXTENSION DeviceExtension;
00942   ULONG Size;
00943 
00944   DPRINT("InterfaceBusSetBusData(%p 0x%lx %p 0x%lx 0x%lx)\n",
00945     Context, DataType, Buffer, Offset, Length);
00946 
00947   if (DataType != PCI_WHICHSPACE_CONFIG)
00948   {
00949     DPRINT("Unknown DataType %lu\n", DataType);
00950     return 0;
00951   }
00952 
00953   DeviceExtension = (PPDO_DEVICE_EXTENSION)((PDEVICE_OBJECT)Context)->DeviceExtension;
00954 
00955   /* Get PCI configuration space */
00956   Size = HalSetBusDataByOffset(PCIConfiguration,
00957                               DeviceExtension->PciDevice->BusNumber,
00958                               DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
00959                               Buffer,
00960                               Offset,
00961                               Length);
00962   return Size;
00963 }
00964 
00965 
00966 static ULONG NTAPI
00967 InterfaceBusGetBusData(
00968   IN PVOID Context,
00969   IN ULONG DataType,
00970   IN PVOID Buffer,
00971   IN ULONG Offset,
00972   IN ULONG Length)
00973 {
00974   PPDO_DEVICE_EXTENSION DeviceExtension;
00975   ULONG Size;
00976 
00977   DPRINT("InterfaceBusGetBusData(%p 0x%lx %p 0x%lx 0x%lx) called\n",
00978     Context, DataType, Buffer, Offset, Length);
00979 
00980   if (DataType != PCI_WHICHSPACE_CONFIG)
00981   {
00982     DPRINT("Unknown DataType %lu\n", DataType);
00983     return 0;
00984   }
00985 
00986   DeviceExtension = (PPDO_DEVICE_EXTENSION)((PDEVICE_OBJECT)Context)->DeviceExtension;
00987 
00988   /* Get PCI configuration space */
00989   Size = HalGetBusDataByOffset(PCIConfiguration,
00990                               DeviceExtension->PciDevice->BusNumber,
00991                               DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
00992                               Buffer,
00993                               Offset,
00994                               Length);
00995   return Size;
00996 }
00997 
00998 
00999 static BOOLEAN NTAPI
01000 InterfacePciDevicePresent(
01001   IN USHORT VendorID,
01002   IN USHORT DeviceID,
01003   IN UCHAR RevisionID,
01004   IN USHORT SubVendorID,
01005   IN USHORT SubSystemID,
01006   IN ULONG Flags)
01007 {
01008   PFDO_DEVICE_EXTENSION FdoDeviceExtension;
01009   PPCI_DEVICE PciDevice;
01010   PLIST_ENTRY CurrentBus, CurrentEntry;
01011   KIRQL OldIrql;
01012   BOOLEAN Found = FALSE;
01013 
01014   KeAcquireSpinLock(&DriverExtension->BusListLock, &OldIrql);
01015   CurrentBus = DriverExtension->BusListHead.Flink;
01016   while (!Found && CurrentBus != &DriverExtension->BusListHead)
01017   {
01018     FdoDeviceExtension = CONTAINING_RECORD(CurrentBus, FDO_DEVICE_EXTENSION, ListEntry);
01019 
01020     KeAcquireSpinLockAtDpcLevel(&FdoDeviceExtension->DeviceListLock);
01021     CurrentEntry = FdoDeviceExtension->DeviceListHead.Flink;
01022     while (!Found && CurrentEntry != &FdoDeviceExtension->DeviceListHead)
01023     {
01024       PciDevice = CONTAINING_RECORD(CurrentEntry, PCI_DEVICE, ListEntry);
01025       if (PciDevice->PciConfig.VendorID == VendorID &&
01026         PciDevice->PciConfig.DeviceID == DeviceID)
01027       {
01028         if (!(Flags & PCI_USE_SUBSYSTEM_IDS) || (
01029           PciDevice->PciConfig.u.type0.SubVendorID == SubVendorID &&
01030           PciDevice->PciConfig.u.type0.SubSystemID == SubSystemID))
01031         {
01032           if (!(Flags & PCI_USE_REVISION) ||
01033             PciDevice->PciConfig.RevisionID == RevisionID)
01034           {
01035             DPRINT("Found the PCI device\n");
01036             Found = TRUE;
01037           }
01038         }
01039       }
01040 
01041       CurrentEntry = CurrentEntry->Flink;
01042     }
01043 
01044     KeReleaseSpinLockFromDpcLevel(&FdoDeviceExtension->DeviceListLock);
01045     CurrentBus = CurrentBus->Flink;
01046   }
01047   KeReleaseSpinLock(&DriverExtension->BusListLock, OldIrql);
01048 
01049   return Found;
01050 }
01051 
01052 
01053 static BOOLEAN
01054 CheckPciDevice(
01055   IN PPCI_COMMON_CONFIG PciConfig,
01056   IN PPCI_DEVICE_PRESENCE_PARAMETERS Parameters)
01057 {
01058   if ((Parameters->Flags & PCI_USE_VENDEV_IDS) && (
01059     PciConfig->VendorID != Parameters->VendorID ||
01060     PciConfig->DeviceID != Parameters->DeviceID))
01061   {
01062     return FALSE;
01063   }
01064   if ((Parameters->Flags & PCI_USE_CLASS_SUBCLASS) && (
01065     PciConfig->BaseClass != Parameters->BaseClass ||
01066     PciConfig->SubClass != Parameters->SubClass))
01067   {
01068     return FALSE;
01069   }
01070   if ((Parameters->Flags & PCI_USE_PROGIF) &&
01071     PciConfig->ProgIf != Parameters->ProgIf)
01072   {
01073     return FALSE;
01074   }
01075   if ((Parameters->Flags & PCI_USE_SUBSYSTEM_IDS) && (
01076     PciConfig->u.type0.SubVendorID != Parameters->SubVendorID ||
01077     PciConfig->u.type0.SubSystemID != Parameters->SubSystemID))
01078   {
01079     return FALSE;
01080   }
01081   if ((Parameters->Flags & PCI_USE_REVISION) &&
01082     PciConfig->RevisionID != Parameters->RevisionID)
01083   {
01084     return FALSE;
01085   }
01086   return TRUE;
01087 }
01088 
01089 
01090 static BOOLEAN NTAPI
01091 InterfacePciDevicePresentEx(
01092   IN PVOID Context,
01093   IN PPCI_DEVICE_PRESENCE_PARAMETERS Parameters)
01094 {
01095   PPDO_DEVICE_EXTENSION DeviceExtension;
01096   PFDO_DEVICE_EXTENSION MyFdoDeviceExtension;
01097   PFDO_DEVICE_EXTENSION FdoDeviceExtension;
01098   PPCI_DEVICE PciDevice;
01099   PLIST_ENTRY CurrentBus, CurrentEntry;
01100   KIRQL OldIrql;
01101   BOOLEAN Found = FALSE;
01102 
01103   DPRINT("InterfacePciDevicePresentEx(%p %p) called\n",
01104     Context, Parameters);
01105 
01106   if (!Parameters || Parameters->Size != sizeof(PCI_DEVICE_PRESENCE_PARAMETERS))
01107     return FALSE;
01108 
01109   DeviceExtension = (PPDO_DEVICE_EXTENSION)((PDEVICE_OBJECT)Context)->DeviceExtension;
01110   MyFdoDeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceExtension->Fdo->DeviceExtension;
01111 
01112   if (Parameters->Flags & PCI_USE_LOCAL_DEVICE)
01113   {
01114     return CheckPciDevice(&DeviceExtension->PciDevice->PciConfig, Parameters);
01115   }
01116 
01117   KeAcquireSpinLock(&DriverExtension->BusListLock, &OldIrql);
01118   CurrentBus = DriverExtension->BusListHead.Flink;
01119   while (!Found && CurrentBus != &DriverExtension->BusListHead)
01120   {
01121     FdoDeviceExtension = CONTAINING_RECORD(CurrentBus, FDO_DEVICE_EXTENSION, ListEntry);
01122     if (!(Parameters->Flags & PCI_USE_LOCAL_BUS) || FdoDeviceExtension == MyFdoDeviceExtension)
01123     {
01124       KeAcquireSpinLockAtDpcLevel(&FdoDeviceExtension->DeviceListLock);
01125       CurrentEntry = FdoDeviceExtension->DeviceListHead.Flink;
01126       while (!Found && CurrentEntry != &FdoDeviceExtension->DeviceListHead)
01127       {
01128         PciDevice = CONTAINING_RECORD(CurrentEntry, PCI_DEVICE, ListEntry);
01129 
01130         if (CheckPciDevice(&PciDevice->PciConfig, Parameters))
01131         {
01132           DPRINT("Found the PCI device\n");
01133           Found = TRUE;
01134         }
01135 
01136         CurrentEntry = CurrentEntry->Flink;
01137       }
01138 
01139       KeReleaseSpinLockFromDpcLevel(&FdoDeviceExtension->DeviceListLock);
01140     }
01141     CurrentBus = CurrentBus->Flink;
01142   }
01143   KeReleaseSpinLock(&DriverExtension->BusListLock, OldIrql);
01144 
01145   return Found;
01146 }
01147 
01148 
01149 static NTSTATUS
01150 PdoQueryInterface(
01151   IN PDEVICE_OBJECT DeviceObject,
01152   IN PIRP Irp,
01153   PIO_STACK_LOCATION IrpSp)
01154 {
01155   NTSTATUS Status;
01156 
01157   UNREFERENCED_PARAMETER(Irp);
01158   if (RtlCompareMemory(IrpSp->Parameters.QueryInterface.InterfaceType,
01159     &GUID_BUS_INTERFACE_STANDARD, sizeof(GUID)) == sizeof(GUID))
01160   {
01161     /* BUS_INTERFACE_STANDARD */
01162     if (IrpSp->Parameters.QueryInterface.Version < 1)
01163       Status = STATUS_NOT_SUPPORTED;
01164     else if (IrpSp->Parameters.QueryInterface.Size < sizeof(BUS_INTERFACE_STANDARD))
01165       Status = STATUS_BUFFER_TOO_SMALL;
01166     else
01167     {
01168       PBUS_INTERFACE_STANDARD BusInterface;
01169       BusInterface = (PBUS_INTERFACE_STANDARD)IrpSp->Parameters.QueryInterface.Interface;
01170       BusInterface->Size = sizeof(BUS_INTERFACE_STANDARD);
01171       BusInterface->Version = 1;
01172       BusInterface->TranslateBusAddress = InterfaceBusTranslateBusAddress;
01173       BusInterface->GetDmaAdapter = InterfaceBusGetDmaAdapter;
01174       BusInterface->SetBusData = InterfaceBusSetBusData;
01175       BusInterface->GetBusData = InterfaceBusGetBusData;
01176       Status = STATUS_SUCCESS;
01177     }
01178   }
01179   else if (RtlCompareMemory(IrpSp->Parameters.QueryInterface.InterfaceType,
01180     &GUID_PCI_DEVICE_PRESENT_INTERFACE, sizeof(GUID)) == sizeof(GUID))
01181   {
01182     /* PCI_DEVICE_PRESENT_INTERFACE */
01183     if (IrpSp->Parameters.QueryInterface.Version < 1)
01184       Status = STATUS_NOT_SUPPORTED;
01185     else if (IrpSp->Parameters.QueryInterface.Size < sizeof(PCI_DEVICE_PRESENT_INTERFACE))
01186       Status = STATUS_BUFFER_TOO_SMALL;
01187     else
01188     {
01189       PPCI_DEVICE_PRESENT_INTERFACE PciDevicePresentInterface;
01190       PciDevicePresentInterface = (PPCI_DEVICE_PRESENT_INTERFACE)IrpSp->Parameters.QueryInterface.Interface;
01191       PciDevicePresentInterface->Size = sizeof(PCI_DEVICE_PRESENT_INTERFACE);
01192       PciDevicePresentInterface->Version = 1;
01193       PciDevicePresentInterface->IsDevicePresent = InterfacePciDevicePresent;
01194       PciDevicePresentInterface->IsDevicePresentEx = InterfacePciDevicePresentEx;
01195       Status = STATUS_SUCCESS;
01196     }
01197   }
01198   else
01199   {
01200     /* Not a supported interface */
01201     return STATUS_NOT_SUPPORTED;
01202   }
01203 
01204   if (NT_SUCCESS(Status))
01205   {
01206     /* Add a reference for the returned interface */
01207     PINTERFACE Interface;
01208     Interface = (PINTERFACE)IrpSp->Parameters.QueryInterface.Interface;
01209     Interface->Context = DeviceObject;
01210     Interface->InterfaceReference = InterfaceReference;
01211     Interface->InterfaceDereference = InterfaceDereference;
01212     Interface->InterfaceReference(Interface->Context);
01213   }
01214 
01215   return Status;
01216 }
01217 
01218 static NTSTATUS
01219 PdoStartDevice(
01220   IN PDEVICE_OBJECT DeviceObject,
01221   IN PIRP Irp,
01222   PIO_STACK_LOCATION IrpSp)
01223 {
01224     PCM_RESOURCE_LIST RawResList = IrpSp->Parameters.StartDevice.AllocatedResources;
01225     PCM_FULL_RESOURCE_DESCRIPTOR RawFullDesc;
01226     PCM_PARTIAL_RESOURCE_DESCRIPTOR RawPartialDesc;
01227     ULONG i, ii;
01228     PPDO_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
01229     UCHAR Irq;
01230     USHORT Command;
01231 
01232     if (!RawResList)
01233         return STATUS_SUCCESS;
01234 
01235     /* TODO: Assign the other resources we get to the card */
01236 
01237     for (i = 0; i < RawResList->Count; i++)
01238     {
01239         RawFullDesc = &RawResList->List[i];
01240 
01241         for (ii = 0; ii < RawFullDesc->PartialResourceList.Count; ii++)
01242         {
01243             RawPartialDesc = &RawFullDesc->PartialResourceList.PartialDescriptors[ii];
01244 
01245             if (RawPartialDesc->Type == CmResourceTypeInterrupt)
01246             {
01247                 DPRINT1("Assigning IRQ %d to PCI device 0x%x on bus 0x%x\n",
01248                         RawPartialDesc->u.Interrupt.Vector,
01249                         DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
01250                         DeviceExtension->PciDevice->BusNumber);
01251 
01252                 Irq = (UCHAR)RawPartialDesc->u.Interrupt.Vector;
01253                 HalSetBusDataByOffset(PCIConfiguration,
01254                                       DeviceExtension->PciDevice->BusNumber,
01255                                       DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
01256                                       &Irq,
01257                                       0x3c /* PCI_INTERRUPT_LINE */,
01258                                       sizeof(UCHAR));
01259             }
01260         }
01261     }
01262 
01263     Command = 0;
01264 
01265     DPRINT1("Enabling command flags for PCI device 0x%x on bus 0x%x: ",
01266             DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
01267             DeviceExtension->PciDevice->BusNumber);
01268     if (DeviceExtension->PciDevice->EnableBusMaster)
01269     {
01270         Command |= PCI_ENABLE_BUS_MASTER;
01271         DbgPrint("[Bus master] ");
01272     }
01273 
01274     if (DeviceExtension->PciDevice->EnableMemorySpace)
01275     {
01276         Command |= PCI_ENABLE_MEMORY_SPACE;
01277         DbgPrint("[Memory space enable] ");
01278     }
01279 
01280     if (DeviceExtension->PciDevice->EnableIoSpace)
01281     {
01282         Command |= PCI_ENABLE_IO_SPACE;
01283         DbgPrint("[I/O space enable] ");
01284     }
01285 
01286     if (Command != 0)
01287     {
01288         DbgPrint("\n");
01289 
01290         /* OR with the previous value */
01291         Command |= DeviceExtension->PciDevice->PciConfig.Command;
01292 
01293         HalSetBusDataByOffset(PCIConfiguration,
01294                               DeviceExtension->PciDevice->BusNumber,
01295                               DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
01296                               &Command,
01297                               FIELD_OFFSET(PCI_COMMON_CONFIG, Command),
01298                               sizeof(USHORT));
01299     }
01300     else
01301     {
01302         DbgPrint("None\n");
01303     }
01304 
01305     return STATUS_SUCCESS;
01306 }
01307 
01308 static NTSTATUS
01309 PdoReadConfig(
01310   IN PDEVICE_OBJECT DeviceObject,
01311   IN PIRP Irp,
01312   PIO_STACK_LOCATION IrpSp)
01313 {
01314   ULONG Size;
01315 
01316   DPRINT("PdoReadConfig() called\n");
01317 
01318   Size = InterfaceBusGetBusData(
01319     DeviceObject,
01320     IrpSp->Parameters.ReadWriteConfig.WhichSpace,
01321     IrpSp->Parameters.ReadWriteConfig.Buffer,
01322     IrpSp->Parameters.ReadWriteConfig.Offset,
01323     IrpSp->Parameters.ReadWriteConfig.Length);
01324 
01325   if (Size != IrpSp->Parameters.ReadWriteConfig.Length)
01326   {
01327     DPRINT1("Size %lu  Length %lu\n", Size, IrpSp->Parameters.ReadWriteConfig.Length);
01328     Irp->IoStatus.Information = 0;
01329     return STATUS_UNSUCCESSFUL;
01330   }
01331 
01332   Irp->IoStatus.Information = Size;
01333 
01334   return STATUS_SUCCESS;
01335 }
01336 
01337 
01338 static NTSTATUS
01339 PdoWriteConfig(
01340   IN PDEVICE_OBJECT DeviceObject,
01341   IN PIRP Irp,
01342   PIO_STACK_LOCATION IrpSp)
01343 {
01344   ULONG Size;
01345 
01346   DPRINT1("PdoWriteConfig() called\n");
01347 
01348   /* Get PCI configuration space */
01349   Size = InterfaceBusSetBusData(
01350     DeviceObject,
01351     IrpSp->Parameters.ReadWriteConfig.WhichSpace,
01352     IrpSp->Parameters.ReadWriteConfig.Buffer,
01353     IrpSp->Parameters.ReadWriteConfig.Offset,
01354     IrpSp->Parameters.ReadWriteConfig.Length);
01355 
01356   if (Size != IrpSp->Parameters.ReadWriteConfig.Length)
01357   {
01358     DPRINT1("Size %lu  Length %lu\n", Size, IrpSp->Parameters.ReadWriteConfig.Length);
01359     Irp->IoStatus.Information = 0;
01360     return STATUS_UNSUCCESSFUL;
01361   }
01362 
01363   Irp->IoStatus.Information = Size;
01364 
01365   return STATUS_SUCCESS;
01366 }
01367 
01368 static NTSTATUS
01369 PdoQueryDeviceRelations(
01370   IN PDEVICE_OBJECT DeviceObject,
01371   IN PIRP Irp,
01372   PIO_STACK_LOCATION IrpSp)
01373 {
01374   PDEVICE_RELATIONS DeviceRelations;
01375 
01376   /* We only support TargetDeviceRelation for child PDOs */
01377   if (IrpSp->Parameters.QueryDeviceRelations.Type != TargetDeviceRelation)
01378       return Irp->IoStatus.Status;
01379 
01380   /* We can do this because we only return 1 PDO for TargetDeviceRelation */
01381   DeviceRelations = ExAllocatePool(PagedPool, sizeof(*DeviceRelations));
01382   if (!DeviceRelations)
01383       return STATUS_INSUFFICIENT_RESOURCES;
01384 
01385   DeviceRelations->Count = 1;
01386   DeviceRelations->Objects[0] = DeviceObject;
01387 
01388   /* The PnP manager will remove this when it is done with the PDO */
01389   ObReferenceObject(DeviceObject);
01390 
01391   Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
01392 
01393   return STATUS_SUCCESS;
01394 }
01395 
01396 static NTSTATUS
01397 PdoSetPower(
01398   IN PDEVICE_OBJECT DeviceObject,
01399   IN PIRP Irp,
01400   PIO_STACK_LOCATION IrpSp)
01401 {
01402   NTSTATUS Status;
01403 
01404   UNREFERENCED_PARAMETER(Irp);
01405   DPRINT("Called\n");
01406 
01407   if (IrpSp->Parameters.Power.Type == DevicePowerState) {
01408     Status = STATUS_SUCCESS;
01409     switch (IrpSp->Parameters.Power.State.SystemState) {
01410     default:
01411       Status = STATUS_UNSUCCESSFUL;
01412     }
01413   } else {
01414     Status = STATUS_UNSUCCESSFUL;
01415   }
01416 
01417   return Status;
01418 }
01419 
01420 
01421 /*** PUBLIC ******************************************************************/
01422 
01423 NTSTATUS
01424 PdoPnpControl(
01425   PDEVICE_OBJECT DeviceObject,
01426   PIRP Irp)
01427 /*
01428  * FUNCTION: Handle Plug and Play IRPs for the child device
01429  * ARGUMENTS:
01430  *     DeviceObject = Pointer to physical device object of the child device
01431  *     Irp          = Pointer to IRP that should be handled
01432  * RETURNS:
01433  *     Status
01434  */
01435 {
01436   PIO_STACK_LOCATION IrpSp;
01437   NTSTATUS Status;
01438 
01439   DPRINT("Called\n");
01440 
01441   Status = Irp->IoStatus.Status;
01442 
01443   IrpSp = IoGetCurrentIrpStackLocation(Irp);
01444 
01445   switch (IrpSp->MinorFunction) {
01446 
01447   case IRP_MN_DEVICE_USAGE_NOTIFICATION:
01448         DPRINT("Unimplemented IRP_MN_DEVICE_USAGE_NOTIFICATION received\n");
01449     break;
01450 
01451   case IRP_MN_EJECT:
01452         DPRINT("Unimplemented IRP_MN_EJECT received\n");
01453     break;
01454 
01455   case IRP_MN_QUERY_BUS_INFORMATION:
01456     Status = PdoQueryBusInformation(DeviceObject, Irp, IrpSp);
01457     break;
01458 
01459   case IRP_MN_QUERY_CAPABILITIES:
01460     Status = PdoQueryCapabilities(DeviceObject, Irp, IrpSp);
01461     break;
01462 
01463   case IRP_MN_QUERY_DEVICE_RELATIONS:
01464     Status = PdoQueryDeviceRelations(DeviceObject, Irp, IrpSp);
01465     break;
01466 
01467   case IRP_MN_QUERY_DEVICE_TEXT:
01468     DPRINT("IRP_MN_QUERY_DEVICE_TEXT received\n");
01469     Status = PdoQueryDeviceText(DeviceObject, Irp, IrpSp);
01470     break;
01471 
01472   case IRP_MN_QUERY_ID:
01473     DPRINT("IRP_MN_QUERY_ID received\n");
01474     Status = PdoQueryId(DeviceObject, Irp, IrpSp);
01475     break;
01476 
01477   case IRP_MN_QUERY_PNP_DEVICE_STATE:
01478     DPRINT("Unimplemented IRP_MN_QUERY_ID received\n");
01479     break;
01480 
01481   case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
01482     DPRINT("IRP_MN_QUERY_RESOURCE_REQUIREMENTS received\n");
01483     Status = PdoQueryResourceRequirements(DeviceObject, Irp, IrpSp);
01484     break;
01485 
01486   case IRP_MN_QUERY_RESOURCES:
01487     DPRINT("IRP_MN_QUERY_RESOURCES received\n");
01488     Status = PdoQueryResources(DeviceObject, Irp, IrpSp);
01489     break;
01490 
01491   case IRP_MN_SET_LOCK:
01492     DPRINT("Unimplemented IRP_MN_SET_LOCK received\n");
01493     break;
01494 
01495   case IRP_MN_START_DEVICE:
01496     Status = PdoStartDevice(DeviceObject, Irp, IrpSp);
01497     break;
01498 
01499   case IRP_MN_QUERY_STOP_DEVICE:
01500   case IRP_MN_CANCEL_STOP_DEVICE:
01501   case IRP_MN_STOP_DEVICE:
01502   case IRP_MN_QUERY_REMOVE_DEVICE:
01503   case IRP_MN_CANCEL_REMOVE_DEVICE:
01504   case IRP_MN_SURPRISE_REMOVAL:
01505     Status = STATUS_SUCCESS;
01506     break;
01507 
01508   case IRP_MN_REMOVE_DEVICE:
01509   {
01510     PPDO_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
01511     PFDO_DEVICE_EXTENSION FdoDeviceExtension = DeviceExtension->Fdo->DeviceExtension;
01512     KIRQL OldIrql;
01513 
01514     /* Remove it from the device list */
01515     KeAcquireSpinLock(&FdoDeviceExtension->DeviceListLock, &OldIrql);
01516     RemoveEntryList(&DeviceExtension->PciDevice->ListEntry);
01517     FdoDeviceExtension->DeviceListCount--;
01518     KeReleaseSpinLock(&FdoDeviceExtension->DeviceListLock, OldIrql);
01519 
01520     /* Free the device */
01521     ExFreePool(DeviceExtension->PciDevice);
01522 
01523     /* Complete the IRP */
01524     Irp->IoStatus.Status = STATUS_SUCCESS;
01525     IoCompleteRequest(Irp, IO_NO_INCREMENT);
01526 
01527     /* Delete the DO */
01528     IoDeleteDevice(DeviceObject);
01529     return STATUS_SUCCESS;
01530   }
01531 
01532   case IRP_MN_QUERY_INTERFACE:
01533     DPRINT("IRP_MN_QUERY_INTERFACE received\n");
01534     Status = PdoQueryInterface(DeviceObject, Irp, IrpSp);
01535     break;
01536 
01537   case IRP_MN_READ_CONFIG:
01538     DPRINT("IRP_MN_READ_CONFIG received\n");
01539     Status = PdoReadConfig(DeviceObject, Irp, IrpSp);
01540     break;
01541 
01542   case IRP_MN_WRITE_CONFIG:
01543     DPRINT("IRP_MN_WRITE_CONFIG received\n");
01544     Status = PdoWriteConfig(DeviceObject, Irp, IrpSp);
01545     break;
01546 
01547   case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
01548     DPRINT("IRP_MN_FILTER_RESOURCE_REQUIREMENTS received\n");
01549     /* Nothing to do */
01550     Irp->IoStatus.Status = Status;
01551     break;
01552 
01553   default:
01554     DPRINT1("Unknown IOCTL 0x%lx\n", IrpSp->MinorFunction);
01555     break;
01556   }
01557 
01558   if (Status != STATUS_PENDING) {
01559     Irp->IoStatus.Status = Status;
01560     IoCompleteRequest(Irp, IO_NO_INCREMENT);
01561   }
01562 
01563   DPRINT("Leaving. Status 0x%X\n", Status);
01564 
01565   return Status;
01566 }
01567 
01568 NTSTATUS
01569 PdoPowerControl(
01570   PDEVICE_OBJECT DeviceObject,
01571   PIRP Irp)
01572 /*
01573  * FUNCTION: Handle power management IRPs for the child device
01574  * ARGUMENTS:
01575  *     DeviceObject = Pointer to physical device object of the child device
01576  *     Irp          = Pointer to IRP that should be handled
01577  * RETURNS:
01578  *     Status
01579  */
01580 {
01581   PIO_STACK_LOCATION IrpSp;
01582   NTSTATUS Status;
01583 
01584   DPRINT("Called\n");
01585 
01586   IrpSp = IoGetCurrentIrpStackLocation(Irp);
01587 
01588   switch (IrpSp->MinorFunction) {
01589   case IRP_MN_SET_POWER:
01590     Status = PdoSetPower(DeviceObject, Irp, IrpSp);
01591     break;
01592 
01593   default:
01594     DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction);
01595     Status = STATUS_NOT_IMPLEMENTED;
01596     break;
01597   }
01598 
01599   if (Status != STATUS_PENDING) {
01600     Irp->IoStatus.Status = Status;
01601     IoCompleteRequest(Irp, IO_NO_INCREMENT);
01602   }
01603 
01604   DPRINT("Leaving. Status 0x%X\n", Status);
01605 
01606   return Status;
01607 }
01608 
01609 /* EOF */

Generated on Sat May 26 2012 04:26:02 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.