Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenpdo.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
1.7.6.1
|