1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: PCI IDE bus driver extension 4 * FILE: drivers/storage/pciidex/pdo.c 5 * PURPOSE: IRP_MJ_PNP operations for PDOs 6 * PROGRAMMERS: Herv� Poussineau (hpoussin@reactos.org) 7 */ 8 9 #include "pciidex.h" 10 11 #include <stdio.h> 12 13 #define NDEBUG 14 #include <debug.h> 15 16 static NTSTATUS 17 PciIdeXPdoQueryId( 18 IN PDEVICE_OBJECT DeviceObject, 19 IN PIRP Irp, 20 OUT ULONG_PTR* Information) 21 { 22 PPDO_DEVICE_EXTENSION DeviceExtension; 23 PFDO_DEVICE_EXTENSION FdoDeviceExtension; 24 WCHAR Buffer[256]; 25 ULONG Index = 0; 26 ULONG IdType; 27 UNICODE_STRING SourceString; 28 UNICODE_STRING String; 29 NTSTATUS Status; 30 31 IdType = IoGetCurrentIrpStackLocation(Irp)->Parameters.QueryId.IdType; 32 DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 33 FdoDeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceExtension->ControllerFdo->DeviceExtension; 34 35 switch (IdType) 36 { 37 case BusQueryDeviceID: 38 { 39 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryDeviceID\n"); 40 RtlInitUnicodeString(&SourceString, L"PCIIDE\\IDEChannel"); 41 break; 42 } 43 case BusQueryHardwareIDs: 44 { 45 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryHardwareIDs\n"); 46 47 switch (FdoDeviceExtension->VendorId) 48 { 49 case 0x0e11: 50 Index += swprintf(&Buffer[Index], L"Compaq-%04x", FdoDeviceExtension->DeviceId) + 1; 51 break; 52 case 0x1039: 53 Index += swprintf(&Buffer[Index], L"SiS-%04x", FdoDeviceExtension->DeviceId) + 1; 54 break; 55 case 0x1050: 56 Index += swprintf(&Buffer[Index], L"WinBond-%04x", FdoDeviceExtension->DeviceId) + 1; 57 break; 58 case 0x1095: 59 Index += swprintf(&Buffer[Index], L"CMD-%04x", FdoDeviceExtension->DeviceId) + 1; 60 break; 61 case 0x8086: 62 { 63 switch (FdoDeviceExtension->DeviceId) 64 { 65 case 0x1230: 66 Index += swprintf(&Buffer[Index], L"Intel-PIIX") + 1; 67 break; 68 case 0x7010: 69 Index += swprintf(&Buffer[Index], L"Intel-PIIX3") + 1; 70 break; 71 case 0x7111: 72 Index += swprintf(&Buffer[Index], L"Intel-PIIX4") + 1; 73 break; 74 default: 75 Index += swprintf(&Buffer[Index], L"Intel-%04x", FdoDeviceExtension->DeviceId) + 1; 76 break; 77 } 78 break; 79 } 80 default: 81 break; 82 } 83 if (DeviceExtension->Channel == 0) 84 Index += swprintf(&Buffer[Index], L"Primary_IDE_Channel") + 1; 85 else 86 Index += swprintf(&Buffer[Index], L"Secondary_IDE_Channel") + 1; 87 Index += swprintf(&Buffer[Index], L"*PNP0600") + 1; 88 Buffer[Index] = UNICODE_NULL; 89 SourceString.Length = SourceString.MaximumLength = Index * sizeof(WCHAR); 90 SourceString.Buffer = Buffer; 91 break; 92 } 93 case BusQueryCompatibleIDs: 94 { 95 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryCompatibleIDs\n"); 96 97 Index += swprintf(&Buffer[Index], L"*PNP0600") + 1; 98 Buffer[Index] = UNICODE_NULL; 99 SourceString.Length = SourceString.MaximumLength = Index * sizeof(WCHAR); 100 SourceString.Buffer = Buffer; 101 break; 102 } 103 case BusQueryInstanceID: 104 { 105 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryInstanceID\n"); 106 swprintf(Buffer, L"%lu", DeviceExtension->Channel); 107 RtlInitUnicodeString(&SourceString, Buffer); 108 break; 109 } 110 default: 111 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_ID / unknown query id type 0x%lx\n", IdType); 112 ASSERT(FALSE); 113 return STATUS_NOT_SUPPORTED; 114 } 115 116 Status = DuplicateUnicodeString( 117 RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE, 118 &SourceString, 119 &String); 120 *Information = (ULONG_PTR)String.Buffer; 121 return Status; 122 } 123 124 static NTSTATUS 125 GetCurrentResources( 126 IN PDEVICE_OBJECT DeviceObject, 127 OUT PULONG CommandPortBase, 128 OUT PULONG ControlPortBase, 129 OUT PULONG BusMasterPortBase, 130 OUT PULONG InterruptVector) 131 { 132 PPDO_DEVICE_EXTENSION DeviceExtension; 133 PFDO_DEVICE_EXTENSION FdoDeviceExtension; 134 ULONG BaseIndex; 135 ULONG BytesRead; 136 PCI_COMMON_CONFIG PciConfig; 137 NTSTATUS ret = STATUS_UNSUCCESSFUL; 138 139 DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 140 FdoDeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceExtension->ControllerFdo->DeviceExtension; 141 BaseIndex = DeviceExtension->Channel * 2; 142 143 BytesRead = (*FdoDeviceExtension->BusInterface->GetBusData)( 144 FdoDeviceExtension->BusInterface->Context, 145 PCI_WHICHSPACE_CONFIG, 146 &PciConfig, 147 0, 148 PCI_COMMON_HDR_LENGTH); 149 if (BytesRead != PCI_COMMON_HDR_LENGTH) 150 return STATUS_IO_DEVICE_ERROR; 151 152 /* We have found a known native pci ide controller */ 153 if ((PciConfig.ProgIf & 0x80) && (PciConfig.u.type0.BaseAddresses[4] & PCI_ADDRESS_IO_SPACE)) 154 { 155 DPRINT("Found IDE Bus Master controller!\n"); 156 *BusMasterPortBase = PciConfig.u.type0.BaseAddresses[4] & PCI_ADDRESS_IO_ADDRESS_MASK; 157 DPRINT(" IDE Bus Master Registers at IO %lx\n", *BusMasterPortBase); 158 } 159 else 160 { 161 *BusMasterPortBase = 0; 162 } 163 164 if ((PciConfig.ProgIf >> BaseIndex) & 0x1) 165 { 166 /* Native mode */ 167 if ((PciConfig.u.type0.BaseAddresses[BaseIndex + 0] & PCI_ADDRESS_IO_SPACE) && 168 (PciConfig.u.type0.BaseAddresses[BaseIndex + 1] & PCI_ADDRESS_IO_SPACE)) 169 { 170 /* Channel is enabled */ 171 *CommandPortBase = PciConfig.u.type0.BaseAddresses[BaseIndex + 0] & PCI_ADDRESS_IO_ADDRESS_MASK; 172 *ControlPortBase = PciConfig.u.type0.BaseAddresses[BaseIndex + 1] & PCI_ADDRESS_IO_ADDRESS_MASK; 173 *InterruptVector = PciConfig.u.type0.InterruptLine; 174 ret = STATUS_SUCCESS; 175 } 176 } 177 else 178 { 179 /* Compatibility mode */ 180 switch (DeviceExtension->Channel) 181 { 182 case 0: 183 if (IoGetConfigurationInformation()->AtDiskPrimaryAddressClaimed) 184 ret = STATUS_INSUFFICIENT_RESOURCES; 185 else 186 { 187 *CommandPortBase = 0x1F0; 188 *ControlPortBase = 0x3F6; 189 *InterruptVector = 14; 190 ret = STATUS_SUCCESS; 191 } 192 break; 193 case 1: 194 if (IoGetConfigurationInformation()->AtDiskSecondaryAddressClaimed) 195 ret = STATUS_INSUFFICIENT_RESOURCES; 196 else 197 { 198 *CommandPortBase = 0x170; 199 *ControlPortBase = 0x376; 200 *InterruptVector = 15; 201 ret = STATUS_SUCCESS; 202 } 203 break; 204 } 205 } 206 207 return ret; 208 } 209 210 static NTSTATUS 211 PciIdeXPdoQueryResourceRequirements( 212 IN PDEVICE_OBJECT DeviceObject, 213 IN PIRP Irp, 214 OUT ULONG_PTR* Information) 215 { 216 ULONG CommandPortBase; 217 ULONG ControlPortBase; 218 ULONG BusMasterPortBase; 219 ULONG InterruptVector; 220 ULONG ListSize; 221 PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList; 222 PIO_RESOURCE_DESCRIPTOR Descriptor; 223 NTSTATUS Status; 224 225 Status = GetCurrentResources(DeviceObject, &CommandPortBase, 226 &ControlPortBase, &BusMasterPortBase, &InterruptVector); 227 if (!NT_SUCCESS(Status)) 228 return Status; 229 230 DPRINT("IDE Channel %lu: IO %x and %x, BM %lx, Irq %lu\n", 231 ((PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->Channel, 232 CommandPortBase, ControlPortBase, 233 BusMasterPortBase, InterruptVector); 234 235 /* FIXME: what to do with BusMasterPortBase? */ 236 237 ListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST) 238 + 2 * sizeof(IO_RESOURCE_DESCRIPTOR); 239 RequirementsList = ExAllocatePool(PagedPool, ListSize); 240 if (!RequirementsList) 241 return STATUS_INSUFFICIENT_RESOURCES; 242 243 RtlZeroMemory(RequirementsList, ListSize); 244 RequirementsList->ListSize = ListSize; 245 RequirementsList->AlternativeLists = 1; 246 247 RequirementsList->List[0].Version = 1; 248 RequirementsList->List[0].Revision = 1; 249 RequirementsList->List[0].Count = 3; 250 251 Descriptor = &RequirementsList->List[0].Descriptors[0]; 252 253 /* Command port base */ 254 Descriptor->Option = 0; /* Required */ 255 Descriptor->Type = CmResourceTypePort; 256 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; 257 Descriptor->Flags = CM_RESOURCE_PORT_IO | 258 CM_RESOURCE_PORT_16_BIT_DECODE | 259 CM_RESOURCE_PORT_POSITIVE_DECODE; 260 Descriptor->u.Port.Length = 7; 261 Descriptor->u.Port.Alignment = 1; 262 Descriptor->u.Port.MinimumAddress.QuadPart = (ULONGLONG)CommandPortBase; 263 Descriptor->u.Port.MaximumAddress.QuadPart = (ULONGLONG)(CommandPortBase + 7 - 1); 264 Descriptor++; 265 266 /* Control port base */ 267 Descriptor->Option = 0; /* Required */ 268 Descriptor->Type = CmResourceTypePort; 269 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; 270 Descriptor->Flags = CM_RESOURCE_PORT_IO | 271 CM_RESOURCE_PORT_16_BIT_DECODE | 272 CM_RESOURCE_PORT_POSITIVE_DECODE; 273 Descriptor->u.Port.Length = 1; 274 Descriptor->u.Port.Alignment = 1; 275 Descriptor->u.Port.MinimumAddress.QuadPart = (ULONGLONG)ControlPortBase; 276 Descriptor->u.Port.MaximumAddress.QuadPart = (ULONGLONG)(ControlPortBase + 1 - 1); 277 Descriptor++; 278 279 /* Interrupt */ 280 Descriptor->Option = 0; /* Required */ 281 Descriptor->Type = CmResourceTypeInterrupt; 282 Descriptor->ShareDisposition = CmResourceShareShared; 283 Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE; 284 Descriptor->u.Interrupt.MinimumVector = InterruptVector; 285 Descriptor->u.Interrupt.MaximumVector = InterruptVector; 286 287 *Information = (ULONG_PTR)RequirementsList; 288 return STATUS_SUCCESS; 289 } 290 291 static NTSTATUS 292 PciIdeXPdoQueryDeviceText( 293 IN PDEVICE_OBJECT DeviceObject, 294 IN PIRP Irp, 295 OUT ULONG_PTR* Information) 296 { 297 PPDO_DEVICE_EXTENSION DeviceExtension; 298 ULONG DeviceTextType; 299 PCWSTR SourceString; 300 UNICODE_STRING String; 301 302 DeviceTextType = IoGetCurrentIrpStackLocation(Irp)->Parameters.QueryDeviceText.DeviceTextType; 303 DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 304 305 switch (DeviceTextType) 306 { 307 case DeviceTextDescription: 308 case DeviceTextLocationInformation: 309 { 310 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / %S\n", 311 DeviceTextType == DeviceTextDescription ? L"DeviceTextDescription" : L"DeviceTextLocationInformation"); 312 if (DeviceExtension->Channel == 0) 313 SourceString = L"Primary channel"; 314 else 315 SourceString = L"Secondary channel"; 316 break; 317 } 318 default: 319 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / unknown type 0x%lx\n", DeviceTextType); 320 ASSERT(FALSE); 321 return STATUS_NOT_SUPPORTED; 322 } 323 324 if (RtlCreateUnicodeString(&String, SourceString)) 325 { 326 *Information = (ULONG_PTR)String.Buffer; 327 return STATUS_SUCCESS; 328 } 329 else 330 return STATUS_INSUFFICIENT_RESOURCES; 331 } 332 333 static NTSTATUS 334 PciIdeXPdoQueryDeviceRelations( 335 IN PDEVICE_OBJECT DeviceObject, 336 OUT PDEVICE_RELATIONS* pDeviceRelations) 337 { 338 PFDO_DEVICE_EXTENSION DeviceExtension; 339 PDEVICE_RELATIONS DeviceRelations; 340 341 DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 342 ASSERT(DeviceExtension->Common.IsFDO); 343 344 DeviceRelations = (PDEVICE_RELATIONS)ExAllocatePool( 345 PagedPool, 346 sizeof(DEVICE_RELATIONS)); 347 if (!DeviceRelations) 348 return STATUS_INSUFFICIENT_RESOURCES; 349 350 ObReferenceObject(DeviceObject); 351 DeviceRelations->Count = 1; 352 DeviceRelations->Objects[0] = DeviceObject; 353 354 *pDeviceRelations = DeviceRelations; 355 return STATUS_SUCCESS; 356 } 357 358 NTSTATUS NTAPI 359 PciIdeXPdoPnpDispatch( 360 IN PDEVICE_OBJECT DeviceObject, 361 IN PIRP Irp) 362 { 363 ULONG MinorFunction; 364 PIO_STACK_LOCATION Stack; 365 ULONG_PTR Information = Irp->IoStatus.Information; 366 NTSTATUS Status; 367 368 Stack = IoGetCurrentIrpStackLocation(Irp); 369 MinorFunction = Stack->MinorFunction; 370 371 switch (MinorFunction) 372 { 373 /* FIXME: 374 * Those are required: 375 * IRP_MN_START_DEVICE (done) 376 * IRP_MN_QUERY_STOP_DEVICE 377 * IRP_MN_STOP_DEVICE 378 * IRP_MN_CANCEL_STOP_DEVICE 379 * IRP_MN_QUERY_REMOVE_DEVICE 380 * IRP_MN_REMOVE_DEVICE 381 * IRP_MN_CANCEL_REMOVE_DEVICE 382 * IRP_MN_SURPRISE_REMOVAL 383 * IRP_MN_QUERY_CAPABILITIES (done) 384 * IRP_MN_QUERY_DEVICE_RELATIONS / TargetDeviceRelations (done) 385 * IRP_MN_QUERY_ID / BusQueryDeviceID (done) 386 * Those may be required/optional: 387 * IRP_MN_DEVICE_USAGE_NOTIFICATION 388 * IRP_MN_QUERY_RESOURCES 389 * IRP_MN_QUERY_RESOURCE_REQUIREMENTS (done) 390 * IRP_MN_QUERY_DEVICE_TEXT 391 * IRP_MN_QUERY_BUS_INFORMATION 392 * IRP_MN_QUERY_INTERFACE 393 * IRP_MN_READ_CONFIG 394 * IRP_MN_WRITE_CONFIG 395 * IRP_MN_EJECT 396 * IRP_MN_SET_LOCK 397 * Those are optional: 398 * IRP_MN_QUERY_DEVICE_RELATIONS / EjectionRelations 399 * IRP_MN_QUERY_ID / BusQueryHardwareIDs (done) 400 * IRP_MN_QUERY_ID / BusQueryCompatibleIDs (done) 401 * IRP_MN_QUERY_ID / BusQueryInstanceID (done) 402 */ 403 case IRP_MN_START_DEVICE: /* 0x00 */ 404 { 405 DPRINT("IRP_MJ_PNP / IRP_MN_START_DEVICE\n"); 406 Status = STATUS_SUCCESS; 407 break; 408 } 409 case IRP_MN_QUERY_REMOVE_DEVICE: /* 0x01 */ 410 { 411 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_REMOVE_DEVICE\n"); 412 Status = STATUS_UNSUCCESSFUL; 413 break; 414 } 415 case IRP_MN_QUERY_DEVICE_RELATIONS: /* 0x07 */ 416 { 417 switch (Stack->Parameters.QueryDeviceRelations.Type) 418 { 419 case TargetDeviceRelation: 420 { 421 PDEVICE_RELATIONS DeviceRelations = NULL; 422 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / TargetDeviceRelation\n"); 423 Status = PciIdeXPdoQueryDeviceRelations(DeviceObject, &DeviceRelations); 424 Information = (ULONG_PTR)DeviceRelations; 425 break; 426 } 427 default: 428 { 429 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n", 430 Stack->Parameters.QueryDeviceRelations.Type); 431 Status = Irp->IoStatus.Status; 432 break; 433 } 434 } 435 break; 436 } 437 case IRP_MN_QUERY_CAPABILITIES: /* 0x09 */ 438 { 439 PDEVICE_CAPABILITIES DeviceCapabilities; 440 ULONG i; 441 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_CAPABILITIES\n"); 442 443 DeviceCapabilities = (PDEVICE_CAPABILITIES)Stack->Parameters.DeviceCapabilities.Capabilities; 444 /* FIXME: capabilities can change with connected device */ 445 DeviceCapabilities->LockSupported = FALSE; 446 DeviceCapabilities->EjectSupported = FALSE; 447 DeviceCapabilities->Removable = TRUE; 448 DeviceCapabilities->DockDevice = FALSE; 449 DeviceCapabilities->UniqueID = FALSE; 450 DeviceCapabilities->SilentInstall = FALSE; 451 DeviceCapabilities->RawDeviceOK = FALSE; 452 DeviceCapabilities->SurpriseRemovalOK = TRUE; 453 DeviceCapabilities->HardwareDisabled = FALSE; /* FIXME */ 454 //DeviceCapabilities->NoDisplayInUI = FALSE; /* FIXME */ 455 DeviceCapabilities->DeviceState[0] = PowerDeviceD0; /* FIXME */ 456 for (i = 0; i < PowerSystemMaximum; i++) 457 DeviceCapabilities->DeviceState[i] = PowerDeviceD3; /* FIXME */ 458 //DeviceCapabilities->DeviceWake = PowerDeviceUndefined; /* FIXME */ 459 DeviceCapabilities->D1Latency = 0; /* FIXME */ 460 DeviceCapabilities->D2Latency = 0; /* FIXME */ 461 DeviceCapabilities->D3Latency = 0; /* FIXME */ 462 Status = STATUS_SUCCESS; 463 break; 464 } 465 case IRP_MN_QUERY_RESOURCES: /* 0x0a */ 466 { 467 /* This IRP is optional; do nothing */ 468 Information = Irp->IoStatus.Information; 469 Status = Irp->IoStatus.Status; 470 break; 471 } 472 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS: /* 0x0b */ 473 { 474 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n"); 475 Status = PciIdeXPdoQueryResourceRequirements(DeviceObject, Irp, &Information); 476 break; 477 } 478 case IRP_MN_QUERY_DEVICE_TEXT: /* 0x0c */ 479 { 480 Status = PciIdeXPdoQueryDeviceText(DeviceObject, Irp, &Information); 481 break; 482 } 483 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS: /* 0x0d */ 484 { 485 DPRINT("IRP_MJ_PNP / IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n"); 486 Information = Irp->IoStatus.Information; 487 Status = Irp->IoStatus.Status; 488 break; 489 } 490 case IRP_MN_QUERY_ID: /* 0x13 */ 491 { 492 Status = PciIdeXPdoQueryId(DeviceObject, Irp, &Information); 493 break; 494 } 495 case IRP_MN_QUERY_PNP_DEVICE_STATE: /* 0x14 */ 496 { 497 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_PNP_DEVICE_STATE\n"); 498 Information |= PNP_DEVICE_NOT_DISABLEABLE; 499 Status = STATUS_SUCCESS; 500 break; 501 } 502 case IRP_MN_QUERY_BUS_INFORMATION: /* 0x15 */ 503 { 504 PPNP_BUS_INFORMATION BusInfo; 505 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_BUS_INFORMATION\n"); 506 507 BusInfo = (PPNP_BUS_INFORMATION)ExAllocatePool(PagedPool, sizeof(PNP_BUS_INFORMATION)); 508 if (!BusInfo) 509 Status = STATUS_INSUFFICIENT_RESOURCES; 510 else 511 { 512 /*RtlCopyMemory( 513 &BusInfo->BusTypeGuid, 514 &GUID_DEVINTERFACE_XXX, 515 sizeof(GUID));*/ 516 BusInfo->LegacyBusType = PNPBus; 517 BusInfo->BusNumber = 0; /* FIXME */ 518 Information = (ULONG_PTR)BusInfo; 519 Status = STATUS_SUCCESS; 520 } 521 break; 522 } 523 default: 524 { 525 /* We can't forward request to the lower driver, because 526 * we are a Pdo, so we don't have lower driver... */ 527 DPRINT1("IRP_MJ_PNP / Unknown minor function 0x%lx\n", MinorFunction); 528 Information = Irp->IoStatus.Information; 529 Status = Irp->IoStatus.Status; 530 } 531 } 532 533 Irp->IoStatus.Information = Information; 534 Irp->IoStatus.Status = Status; 535 IoCompleteRequest(Irp, IO_NO_INCREMENT); 536 return Status; 537 } 538