1 /* 2 * PROJECT: ReactOS Storage Stack / SCSIPORT storage port library 3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) 4 * PURPOSE: Main and exported functions 5 * COPYRIGHT: Eric Kohl (eric.kohl@reactos.org) 6 * Aleksey Bragin (aleksey@reactos.org) 7 * 2020 Victor Perevertkin (victor.perevertkin@reactos.org) 8 */ 9 10 /* INCLUDES *****************************************************************/ 11 12 #include "scsiport.h" 13 14 #define NDEBUG 15 #include <debug.h> 16 17 ULONG InternalDebugLevel = 0x00; 18 19 #undef ScsiPortMoveMemory 20 21 /* GLOBALS *******************************************************************/ 22 23 static BOOLEAN 24 SpiGetPciConfigData(IN PDRIVER_OBJECT DriverObject, 25 IN PDEVICE_OBJECT DeviceObject, 26 IN struct _HW_INITIALIZATION_DATA *HwInitializationData, 27 IN OUT PPORT_CONFIGURATION_INFORMATION PortConfig, 28 IN PUNICODE_STRING RegistryPath, 29 IN ULONG BusNumber, 30 IN OUT PPCI_SLOT_NUMBER NextSlotNumber); 31 32 static NTSTATUS NTAPI 33 ScsiPortCreateClose(IN PDEVICE_OBJECT DeviceObject, 34 IN PIRP Irp); 35 36 static VOID NTAPI 37 ScsiPortIoTimer(PDEVICE_OBJECT DeviceObject, 38 PVOID Context); 39 40 VOID NTAPI 41 SpiMiniportTimerDpc(IN struct _KDPC *Dpc, 42 IN PVOID DeviceObject, 43 IN PVOID SystemArgument1, 44 IN PVOID SystemArgument2); 45 46 static NTSTATUS 47 SpiCreatePortConfig(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension, 48 PHW_INITIALIZATION_DATA HwInitData, 49 PCONFIGURATION_INFO InternalConfigInfo, 50 PPORT_CONFIGURATION_INFORMATION ConfigInfo, 51 BOOLEAN FirstCall); 52 53 NTSTATUS NTAPI 54 SpQueryDeviceCallout(IN PVOID Context, 55 IN PUNICODE_STRING PathName, 56 IN INTERFACE_TYPE BusType, 57 IN ULONG BusNumber, 58 IN PKEY_VALUE_FULL_INFORMATION *BusInformation, 59 IN CONFIGURATION_TYPE ControllerType, 60 IN ULONG ControllerNumber, 61 IN PKEY_VALUE_FULL_INFORMATION *ControllerInformation, 62 IN CONFIGURATION_TYPE PeripheralType, 63 IN ULONG PeripheralNumber, 64 IN PKEY_VALUE_FULL_INFORMATION *PeripheralInformation); 65 66 static VOID 67 SpiParseDeviceInfo(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension, 68 IN HANDLE Key, 69 IN PPORT_CONFIGURATION_INFORMATION ConfigInfo, 70 IN PCONFIGURATION_INFO InternalConfigInfo, 71 IN PUCHAR Buffer); 72 73 static VOID 74 SpiResourceToConfig(IN PHW_INITIALIZATION_DATA HwInitializationData, 75 IN PCM_FULL_RESOURCE_DESCRIPTOR ResourceDescriptor, 76 IN PPORT_CONFIGURATION_INFORMATION PortConfig); 77 78 static PCM_RESOURCE_LIST 79 SpiConfigToResource(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension, 80 PPORT_CONFIGURATION_INFORMATION PortConfig); 81 82 static NTSTATUS 83 SpiAllocateCommonBuffer(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension, ULONG NonCachedSize); 84 85 NTHALAPI ULONG NTAPI HalGetBusData(BUS_DATA_TYPE, ULONG, ULONG, PVOID, ULONG); 86 NTHALAPI ULONG NTAPI HalGetInterruptVector(INTERFACE_TYPE, ULONG, ULONG, ULONG, PKIRQL, PKAFFINITY); 87 NTHALAPI NTSTATUS NTAPI HalAssignSlotResources(PUNICODE_STRING, PUNICODE_STRING, PDRIVER_OBJECT, PDEVICE_OBJECT, INTERFACE_TYPE, ULONG, ULONG, PCM_RESOURCE_LIST *); 88 89 /* FUNCTIONS *****************************************************************/ 90 91 /********************************************************************** 92 * NAME EXPORTED 93 * DriverEntry 94 * 95 * DESCRIPTION 96 * This function initializes the driver. 97 * 98 * RUN LEVEL 99 * PASSIVE_LEVEL 100 * 101 * ARGUMENTS 102 * DriverObject 103 * System allocated Driver Object for this driver. 104 * 105 * RegistryPath 106 * Name of registry driver service key. 107 * 108 * RETURN VALUE 109 * Status. 110 */ 111 112 NTSTATUS NTAPI 113 DriverEntry(IN PDRIVER_OBJECT DriverObject, 114 IN PUNICODE_STRING RegistryPath) 115 { 116 return STATUS_SUCCESS; 117 } 118 119 VOID 120 NTAPI 121 ScsiPortUnload( 122 _In_ PDRIVER_OBJECT DriverObject) 123 { 124 // no-op 125 } 126 127 NTSTATUS 128 NTAPI 129 ScsiPortDispatchPnp( 130 PDEVICE_OBJECT DeviceObject, 131 PIRP Irp) 132 { 133 if (((PSCSI_PORT_COMMON_EXTENSION)DeviceObject->DeviceExtension)->IsFDO) 134 { 135 return FdoDispatchPnp(DeviceObject, Irp); 136 } 137 else 138 { 139 return PdoDispatchPnp(DeviceObject, Irp); 140 } 141 } 142 143 NTSTATUS 144 NTAPI 145 ScsiPortAddDevice( 146 _In_ PDRIVER_OBJECT DriverObject, 147 _In_ PDEVICE_OBJECT PhysicalDeviceObject) 148 { 149 150 DPRINT("AddDevice no-op DriverObj: %p, PDO: %p\n", DriverObject, PhysicalDeviceObject); 151 152 return STATUS_SUCCESS; 153 } 154 155 156 /********************************************************************** 157 * NAME EXPORTED 158 * ScsiDebugPrint 159 * 160 * DESCRIPTION 161 * Prints debugging messages. 162 * 163 * RUN LEVEL 164 * PASSIVE_LEVEL 165 * 166 * ARGUMENTS 167 * DebugPrintLevel 168 * Debug level of the given message. 169 * 170 * DebugMessage 171 * Pointer to printf()-compatible format string. 172 * 173 * ... 174 Additional output data (see printf()). 175 * 176 * RETURN VALUE 177 * None. 178 * 179 * @implemented 180 */ 181 182 VOID 183 ScsiDebugPrint(IN ULONG DebugPrintLevel, 184 IN PCHAR DebugMessage, 185 ...) 186 { 187 char Buffer[256]; 188 va_list ap; 189 190 if (DebugPrintLevel > InternalDebugLevel) 191 return; 192 193 va_start(ap, DebugMessage); 194 vsprintf(Buffer, DebugMessage, ap); 195 va_end(ap); 196 197 DbgPrint(Buffer); 198 } 199 200 /* An internal helper function for ScsiPortCompleteRequest */ 201 VOID 202 NTAPI 203 SpiCompleteRequest(IN PVOID HwDeviceExtension, 204 IN PSCSI_REQUEST_BLOCK_INFO SrbInfo, 205 IN UCHAR SrbStatus) 206 { 207 PSCSI_REQUEST_BLOCK Srb; 208 209 /* Get current SRB */ 210 Srb = SrbInfo->Srb; 211 212 /* Return if there is no SRB or it is not active */ 213 if (!Srb || !(Srb->SrbFlags & SRB_FLAGS_IS_ACTIVE)) return; 214 215 /* Set status */ 216 Srb->SrbStatus = SrbStatus; 217 218 /* Set data transfered to 0 */ 219 Srb->DataTransferLength = 0; 220 221 /* Notify */ 222 ScsiPortNotification(RequestComplete, 223 HwDeviceExtension, 224 Srb); 225 } 226 227 /* 228 * @unimplemented 229 */ 230 VOID NTAPI 231 ScsiPortCompleteRequest(IN PVOID HwDeviceExtension, 232 IN UCHAR PathId, 233 IN UCHAR TargetId, 234 IN UCHAR Lun, 235 IN UCHAR SrbStatus) 236 { 237 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension; 238 PSCSI_PORT_LUN_EXTENSION LunExtension; 239 PSCSI_REQUEST_BLOCK_INFO SrbInfo; 240 PLIST_ENTRY ListEntry; 241 242 DPRINT("ScsiPortCompleteRequest() called\n"); 243 244 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension, 245 SCSI_PORT_DEVICE_EXTENSION, 246 MiniPortDeviceExtension); 247 248 /* Go through all buses */ 249 for (UINT8 pathId = 0; pathId < DeviceExtension->NumberOfBuses; pathId++) 250 { 251 PSCSI_BUS_INFO bus = &DeviceExtension->Buses[pathId]; 252 253 /* Go through all logical units */ 254 for (PLIST_ENTRY lunEntry = bus->LunsListHead.Flink; 255 lunEntry != &bus->LunsListHead; 256 lunEntry = lunEntry->Flink) 257 { 258 LunExtension = CONTAINING_RECORD(lunEntry, SCSI_PORT_LUN_EXTENSION, LunEntry); 259 260 /* Now match what caller asked with what we are at now */ 261 if ((PathId == SP_UNTAGGED || PathId == LunExtension->PathId) && 262 (TargetId == SP_UNTAGGED || TargetId == LunExtension->TargetId) && 263 (Lun == SP_UNTAGGED || Lun == LunExtension->Lun)) 264 { 265 /* Yes, that's what caller asked for. Complete abort requests */ 266 if (LunExtension->CompletedAbortRequests) 267 { 268 /* TODO: Save SrbStatus in this request */ 269 DPRINT1("Completing abort request without setting SrbStatus!\n"); 270 271 /* Issue a notification request */ 272 ScsiPortNotification(RequestComplete, 273 HwDeviceExtension, 274 LunExtension->CompletedAbortRequests); 275 } 276 277 /* Complete the request using our helper */ 278 SpiCompleteRequest(HwDeviceExtension, 279 &LunExtension->SrbInfo, 280 SrbStatus); 281 282 /* Go through the queue and complete everything there too */ 283 ListEntry = LunExtension->SrbInfo.Requests.Flink; 284 while (ListEntry != &LunExtension->SrbInfo.Requests) 285 { 286 /* Get the actual SRB info entry */ 287 SrbInfo = CONTAINING_RECORD(ListEntry, 288 SCSI_REQUEST_BLOCK_INFO, 289 Requests); 290 291 /* Complete it */ 292 SpiCompleteRequest(HwDeviceExtension, 293 SrbInfo, 294 SrbStatus); 295 296 /* Advance to the next request in queue */ 297 ListEntry = SrbInfo->Requests.Flink; 298 } 299 } 300 } 301 } 302 } 303 304 /* 305 * @unimplemented 306 */ 307 VOID NTAPI 308 ScsiPortFlushDma(IN PVOID HwDeviceExtension) 309 { 310 DPRINT("ScsiPortFlushDma()\n"); 311 UNIMPLEMENTED; 312 } 313 314 315 /* 316 * @implemented 317 */ 318 VOID NTAPI 319 ScsiPortFreeDeviceBase(IN PVOID HwDeviceExtension, 320 IN PVOID MappedAddress) 321 { 322 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension; 323 PMAPPED_ADDRESS NextMa, LastMa; 324 325 //DPRINT("ScsiPortFreeDeviceBase() called\n"); 326 327 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension, 328 SCSI_PORT_DEVICE_EXTENSION, 329 MiniPortDeviceExtension); 330 331 /* Initialize our pointers */ 332 NextMa = DeviceExtension->MappedAddressList; 333 LastMa = NextMa; 334 335 while (NextMa) 336 { 337 if (NextMa->MappedAddress == MappedAddress) 338 { 339 /* Unmap it first */ 340 MmUnmapIoSpace(MappedAddress, NextMa->NumberOfBytes); 341 342 /* Remove it from the list */ 343 if (NextMa == DeviceExtension->MappedAddressList) 344 { 345 /* Remove the first entry */ 346 DeviceExtension->MappedAddressList = NextMa->NextMappedAddress; 347 } 348 else 349 { 350 LastMa->NextMappedAddress = NextMa->NextMappedAddress; 351 } 352 353 /* Free the resources and quit */ 354 ExFreePool(NextMa); 355 356 return; 357 } 358 else 359 { 360 LastMa = NextMa; 361 NextMa = NextMa->NextMappedAddress; 362 } 363 } 364 } 365 366 367 /* 368 * @implemented 369 */ 370 ULONG NTAPI 371 ScsiPortGetBusData(IN PVOID DeviceExtension, 372 IN ULONG BusDataType, 373 IN ULONG SystemIoBusNumber, 374 IN ULONG SlotNumber, 375 IN PVOID Buffer, 376 IN ULONG Length) 377 { 378 DPRINT("ScsiPortGetBusData()\n"); 379 380 if (Length) 381 { 382 /* If Length is non-zero, just forward the call to 383 HalGetBusData() function */ 384 return HalGetBusData(BusDataType, 385 SystemIoBusNumber, 386 SlotNumber, 387 Buffer, 388 Length); 389 } 390 391 /* We have a more complex case here */ 392 UNIMPLEMENTED; 393 return 0; 394 } 395 396 /* 397 * @implemented 398 */ 399 ULONG NTAPI 400 ScsiPortSetBusDataByOffset(IN PVOID DeviceExtension, 401 IN ULONG BusDataType, 402 IN ULONG SystemIoBusNumber, 403 IN ULONG SlotNumber, 404 IN PVOID Buffer, 405 IN ULONG Offset, 406 IN ULONG Length) 407 { 408 DPRINT("ScsiPortSetBusDataByOffset()\n"); 409 return HalSetBusDataByOffset(BusDataType, 410 SystemIoBusNumber, 411 SlotNumber, 412 Buffer, 413 Offset, 414 Length); 415 } 416 417 /* 418 * @implemented 419 */ 420 PVOID NTAPI 421 ScsiPortGetDeviceBase(IN PVOID HwDeviceExtension, 422 IN INTERFACE_TYPE BusType, 423 IN ULONG SystemIoBusNumber, 424 IN SCSI_PHYSICAL_ADDRESS IoAddress, 425 IN ULONG NumberOfBytes, 426 IN BOOLEAN InIoSpace) 427 { 428 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension; 429 PHYSICAL_ADDRESS TranslatedAddress; 430 PMAPPED_ADDRESS DeviceBase; 431 ULONG AddressSpace; 432 PVOID MappedAddress; 433 434 //DPRINT ("ScsiPortGetDeviceBase() called\n"); 435 436 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension, 437 SCSI_PORT_DEVICE_EXTENSION, 438 MiniPortDeviceExtension); 439 440 AddressSpace = (ULONG)InIoSpace; 441 if (HalTranslateBusAddress(BusType, 442 SystemIoBusNumber, 443 IoAddress, 444 &AddressSpace, 445 &TranslatedAddress) == FALSE) 446 { 447 return NULL; 448 } 449 450 /* i/o space */ 451 if (AddressSpace != 0) 452 return((PVOID)(ULONG_PTR)TranslatedAddress.QuadPart); 453 454 MappedAddress = MmMapIoSpace(TranslatedAddress, 455 NumberOfBytes, 456 FALSE); 457 458 DeviceBase = ExAllocatePoolWithTag(NonPagedPool, 459 sizeof(MAPPED_ADDRESS), TAG_SCSIPORT); 460 461 if (DeviceBase == NULL) 462 return MappedAddress; 463 464 DeviceBase->MappedAddress = MappedAddress; 465 DeviceBase->NumberOfBytes = NumberOfBytes; 466 DeviceBase->IoAddress = IoAddress; 467 DeviceBase->BusNumber = SystemIoBusNumber; 468 469 /* Link it to the Device Extension list */ 470 DeviceBase->NextMappedAddress = DeviceExtension->MappedAddressList; 471 DeviceExtension->MappedAddressList = DeviceBase; 472 473 return MappedAddress; 474 } 475 476 /* 477 * @unimplemented 478 */ 479 PVOID NTAPI 480 ScsiPortGetLogicalUnit(IN PVOID HwDeviceExtension, 481 IN UCHAR PathId, 482 IN UCHAR TargetId, 483 IN UCHAR Lun) 484 { 485 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension; 486 PSCSI_PORT_LUN_EXTENSION LunExtension; 487 488 DPRINT("ScsiPortGetLogicalUnit() called\n"); 489 490 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension, 491 SCSI_PORT_DEVICE_EXTENSION, 492 MiniPortDeviceExtension); 493 494 /* Check the extension size */ 495 if (!DeviceExtension->LunExtensionSize) 496 { 497 /* They didn't want one */ 498 return NULL; 499 } 500 501 LunExtension = GetLunByPath(DeviceExtension, PathId, TargetId, Lun); 502 503 /* Check that the logical unit exists */ 504 if (!LunExtension) 505 { 506 /* Nope, return NULL */ 507 return NULL; 508 } 509 510 /* Return the logical unit miniport extension */ 511 return (LunExtension + 1); 512 } 513 514 515 /* 516 * @implemented 517 */ 518 SCSI_PHYSICAL_ADDRESS NTAPI 519 ScsiPortGetPhysicalAddress(IN PVOID HwDeviceExtension, 520 IN PSCSI_REQUEST_BLOCK Srb OPTIONAL, 521 IN PVOID VirtualAddress, 522 OUT ULONG *Length) 523 { 524 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension; 525 SCSI_PHYSICAL_ADDRESS PhysicalAddress; 526 SIZE_T BufferLength = 0; 527 ULONG_PTR Offset; 528 PSCSI_SG_ADDRESS SGList; 529 PSCSI_REQUEST_BLOCK_INFO SrbInfo; 530 531 DPRINT("ScsiPortGetPhysicalAddress(%p %p %p %p)\n", 532 HwDeviceExtension, Srb, VirtualAddress, Length); 533 534 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension, 535 SCSI_PORT_DEVICE_EXTENSION, 536 MiniPortDeviceExtension); 537 538 if (Srb == NULL || Srb->SenseInfoBuffer == VirtualAddress) 539 { 540 /* Simply look it up in the allocated common buffer */ 541 Offset = (PUCHAR)VirtualAddress - (PUCHAR)DeviceExtension->SrbExtensionBuffer; 542 543 BufferLength = DeviceExtension->CommonBufferLength - Offset; 544 PhysicalAddress.QuadPart = DeviceExtension->PhysicalAddress.QuadPart + Offset; 545 } 546 else if (DeviceExtension->MapRegisters) 547 { 548 PIO_STACK_LOCATION IoStack = IoGetCurrentIrpStackLocation(Srb->OriginalRequest); 549 PSCSI_PORT_LUN_EXTENSION LunExtension = IoStack->DeviceObject->DeviceExtension; 550 ASSERT(LunExtension && !LunExtension->Common.IsFDO); 551 552 /* Scatter-gather list must be used */ 553 SrbInfo = SpiGetSrbData(DeviceExtension, LunExtension, Srb->QueueTag); 554 555 SGList = SrbInfo->ScatterGather; 556 557 /* Find needed item in the SG list */ 558 Offset = (PCHAR)VirtualAddress - (PCHAR)Srb->DataBuffer; 559 while (Offset >= SGList->Length) 560 { 561 Offset -= SGList->Length; 562 SGList++; 563 } 564 565 /* We're done, store length and physical address */ 566 BufferLength = SGList->Length - Offset; 567 PhysicalAddress.QuadPart = SGList->PhysicalAddress.QuadPart + Offset; 568 } 569 else 570 { 571 /* Nothing */ 572 PhysicalAddress.QuadPart = (LONGLONG)(SP_UNINITIALIZED_VALUE); 573 } 574 575 *Length = (ULONG)BufferLength; 576 return PhysicalAddress; 577 } 578 579 580 /* 581 * @unimplemented 582 */ 583 PSCSI_REQUEST_BLOCK NTAPI 584 ScsiPortGetSrb(IN PVOID DeviceExtension, 585 IN UCHAR PathId, 586 IN UCHAR TargetId, 587 IN UCHAR Lun, 588 IN LONG QueueTag) 589 { 590 DPRINT1("ScsiPortGetSrb() unimplemented\n"); 591 UNIMPLEMENTED; 592 return NULL; 593 } 594 595 596 /* 597 * @implemented 598 */ 599 PVOID NTAPI 600 ScsiPortGetUncachedExtension(IN PVOID HwDeviceExtension, 601 IN PPORT_CONFIGURATION_INFORMATION ConfigInfo, 602 IN ULONG NumberOfBytes) 603 { 604 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension; 605 DEVICE_DESCRIPTION DeviceDescription; 606 ULONG MapRegistersCount; 607 NTSTATUS Status; 608 609 DPRINT("ScsiPortGetUncachedExtension(%p %p %lu)\n", 610 HwDeviceExtension, ConfigInfo, NumberOfBytes); 611 612 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension, 613 SCSI_PORT_DEVICE_EXTENSION, 614 MiniPortDeviceExtension); 615 616 /* Check for allocated common DMA buffer */ 617 if (DeviceExtension->SrbExtensionBuffer != NULL) 618 { 619 DPRINT1("The HBA has already got a common DMA buffer!\n"); 620 return NULL; 621 } 622 623 /* Check for DMA adapter object */ 624 if (DeviceExtension->AdapterObject == NULL) 625 { 626 /* Initialize DMA adapter description */ 627 RtlZeroMemory(&DeviceDescription, sizeof(DEVICE_DESCRIPTION)); 628 629 DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION; 630 DeviceDescription.Master = ConfigInfo->Master; 631 DeviceDescription.ScatterGather = ConfigInfo->ScatterGather; 632 DeviceDescription.DemandMode = ConfigInfo->DemandMode; 633 DeviceDescription.Dma32BitAddresses = ConfigInfo->Dma32BitAddresses; 634 DeviceDescription.BusNumber = ConfigInfo->SystemIoBusNumber; 635 DeviceDescription.DmaChannel = ConfigInfo->DmaChannel; 636 DeviceDescription.InterfaceType = ConfigInfo->AdapterInterfaceType; 637 DeviceDescription.DmaWidth = ConfigInfo->DmaWidth; 638 DeviceDescription.DmaSpeed = ConfigInfo->DmaSpeed; 639 DeviceDescription.MaximumLength = ConfigInfo->MaximumTransferLength; 640 DeviceDescription.DmaPort = ConfigInfo->DmaPort; 641 642 /* Get a DMA adapter object */ 643 DeviceExtension->AdapterObject = 644 HalGetAdapter(&DeviceDescription, &MapRegistersCount); 645 646 /* Fail in case of error */ 647 if (DeviceExtension->AdapterObject == NULL) 648 { 649 DPRINT1("HalGetAdapter() failed\n"); 650 return NULL; 651 } 652 653 /* Set number of physical breaks */ 654 if (ConfigInfo->NumberOfPhysicalBreaks != 0 && 655 MapRegistersCount > ConfigInfo->NumberOfPhysicalBreaks) 656 { 657 DeviceExtension->PortCapabilities.MaximumPhysicalPages = 658 ConfigInfo->NumberOfPhysicalBreaks; 659 } 660 else 661 { 662 DeviceExtension->PortCapabilities.MaximumPhysicalPages = MapRegistersCount; 663 } 664 } 665 666 /* Update auto request sense feature */ 667 DeviceExtension->SupportsAutoSense = ConfigInfo->AutoRequestSense; 668 669 /* Update Srb extension size */ 670 if (DeviceExtension->SrbExtensionSize != ConfigInfo->SrbExtensionSize) 671 DeviceExtension->SrbExtensionSize = ConfigInfo->SrbExtensionSize; 672 673 /* Update Srb extension alloc flag */ 674 if (ConfigInfo->AutoRequestSense || DeviceExtension->SrbExtensionSize) 675 DeviceExtension->NeedSrbExtensionAlloc = TRUE; 676 677 /* Allocate a common DMA buffer */ 678 Status = SpiAllocateCommonBuffer(DeviceExtension, NumberOfBytes); 679 680 if (!NT_SUCCESS(Status)) 681 { 682 DPRINT1("SpiAllocateCommonBuffer() failed with Status = 0x%08X!\n", Status); 683 return NULL; 684 } 685 686 return DeviceExtension->NonCachedExtension; 687 } 688 689 static NTSTATUS 690 SpiAllocateCommonBuffer(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension, ULONG NonCachedSize) 691 { 692 PVOID *SrbExtension, CommonBuffer; 693 ULONG CommonBufferLength, BufSize; 694 695 /* If size is 0, set it to 16 */ 696 if (!DeviceExtension->SrbExtensionSize) 697 DeviceExtension->SrbExtensionSize = 16; 698 699 /* Calculate size */ 700 BufSize = DeviceExtension->SrbExtensionSize; 701 702 /* Add autosense data size if needed */ 703 if (DeviceExtension->SupportsAutoSense) 704 BufSize += sizeof(SENSE_DATA); 705 706 707 /* Round it */ 708 BufSize = (BufSize + sizeof(LONGLONG) - 1) & ~(sizeof(LONGLONG) - 1); 709 710 /* Sum up into the total common buffer length, and round it to page size */ 711 CommonBufferLength = 712 ROUND_TO_PAGES(NonCachedSize + BufSize * DeviceExtension->RequestsNumber); 713 714 /* Allocate it */ 715 if (!DeviceExtension->AdapterObject) 716 { 717 /* From nonpaged pool if there is no DMA */ 718 CommonBuffer = ExAllocatePoolWithTag(NonPagedPool, CommonBufferLength, TAG_SCSIPORT); 719 } 720 else 721 { 722 /* Perform a full request since we have a DMA adapter*/ 723 CommonBuffer = HalAllocateCommonBuffer(DeviceExtension->AdapterObject, 724 CommonBufferLength, 725 &DeviceExtension->PhysicalAddress, 726 FALSE ); 727 } 728 729 /* Fail in case of error */ 730 if (!CommonBuffer) 731 return STATUS_INSUFFICIENT_RESOURCES; 732 733 /* Zero it */ 734 RtlZeroMemory(CommonBuffer, CommonBufferLength); 735 736 /* Store its size in Device Extension */ 737 DeviceExtension->CommonBufferLength = CommonBufferLength; 738 739 /* SrbExtension buffer is located at the beginning of the buffer */ 740 DeviceExtension->SrbExtensionBuffer = CommonBuffer; 741 742 /* Non-cached extension buffer is located at the end of 743 the common buffer */ 744 if (NonCachedSize) 745 { 746 CommonBufferLength -= NonCachedSize; 747 DeviceExtension->NonCachedExtension = (PUCHAR)CommonBuffer + CommonBufferLength; 748 } 749 else 750 { 751 DeviceExtension->NonCachedExtension = NULL; 752 } 753 754 if (DeviceExtension->NeedSrbExtensionAlloc) 755 { 756 /* Look up how many SRB data structures we need */ 757 DeviceExtension->SrbDataCount = CommonBufferLength / BufSize; 758 759 /* Initialize the free SRB extensions list */ 760 SrbExtension = (PVOID *)CommonBuffer; 761 DeviceExtension->FreeSrbExtensions = SrbExtension; 762 763 /* Fill the remaining pointers (if we have more than 1 SRB) */ 764 while (CommonBufferLength >= 2 * BufSize) 765 { 766 *SrbExtension = (PVOID*)((PCHAR)SrbExtension + BufSize); 767 SrbExtension = *SrbExtension; 768 769 CommonBufferLength -= BufSize; 770 } 771 } 772 773 return STATUS_SUCCESS; 774 } 775 776 777 778 /* 779 * @implemented 780 */ 781 PVOID NTAPI 782 ScsiPortGetVirtualAddress(IN PVOID HwDeviceExtension, 783 IN SCSI_PHYSICAL_ADDRESS PhysicalAddress) 784 { 785 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension; 786 ULONG Offset; 787 788 DPRINT("ScsiPortGetVirtualAddress(%p %I64x)\n", 789 HwDeviceExtension, PhysicalAddress.QuadPart); 790 791 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension, 792 SCSI_PORT_DEVICE_EXTENSION, 793 MiniPortDeviceExtension); 794 795 if (DeviceExtension->PhysicalAddress.QuadPart > PhysicalAddress.QuadPart) 796 return NULL; 797 798 Offset = (ULONG)(PhysicalAddress.QuadPart - DeviceExtension->PhysicalAddress.QuadPart); 799 800 if (Offset >= DeviceExtension->CommonBufferLength) 801 return NULL; 802 803 return (PVOID)((ULONG_PTR)DeviceExtension->SrbExtensionBuffer + Offset); 804 } 805 806 /********************************************************************** 807 * NAME EXPORTED 808 * ScsiPortInitialize 809 * 810 * DESCRIPTION 811 * Initializes SCSI port driver specific data. 812 * 813 * RUN LEVEL 814 * PASSIVE_LEVEL 815 * 816 * ARGUMENTS 817 * Argument1 818 * Pointer to the miniport driver's driver object. 819 * 820 * Argument2 821 * Pointer to the miniport driver's registry path. 822 * 823 * HwInitializationData 824 * Pointer to port driver specific configuration data. 825 * 826 * HwContext 827 Miniport driver specific context. 828 * 829 * RETURN VALUE 830 * Status. 831 * 832 * @implemented 833 */ 834 835 ULONG NTAPI 836 ScsiPortInitialize( 837 IN PVOID Argument1, 838 IN PVOID Argument2, 839 IN struct _HW_INITIALIZATION_DATA *HwInitializationData, 840 IN PVOID HwContext) 841 { 842 PDRIVER_OBJECT DriverObject = (PDRIVER_OBJECT)Argument1; 843 PUNICODE_STRING RegistryPath = (PUNICODE_STRING)Argument2; 844 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension = NULL; 845 PCONFIGURATION_INFORMATION SystemConfig; 846 PPORT_CONFIGURATION_INFORMATION PortConfig; 847 CONFIGURATION_INFO ConfigInfo; 848 ULONG DeviceExtensionSize; 849 ULONG PortConfigSize; 850 BOOLEAN Again; 851 BOOLEAN DeviceFound = FALSE; 852 BOOLEAN FirstConfigCall = TRUE; 853 ULONG Result; 854 NTSTATUS Status; 855 ULONG MaxBus; 856 PCI_SLOT_NUMBER SlotNumber; 857 858 PDEVICE_OBJECT PortDeviceObject; 859 UNICODE_STRING DeviceName; 860 PIO_SCSI_CAPABILITIES PortCapabilities; 861 862 PCM_RESOURCE_LIST ResourceList; 863 864 DPRINT ("ScsiPortInitialize() called!\n"); 865 866 /* Check params for validity */ 867 if ((HwInitializationData->HwInitialize == NULL) || 868 (HwInitializationData->HwStartIo == NULL) || 869 (HwInitializationData->HwInterrupt == NULL) || 870 (HwInitializationData->HwFindAdapter == NULL) || 871 (HwInitializationData->HwResetBus == NULL)) 872 { 873 return STATUS_REVISION_MISMATCH; 874 } 875 876 PSCSI_PORT_DRIVER_EXTENSION driverExtension; 877 878 // ScsiPortInitialize may be called multiple times by the same driver 879 driverExtension = IoGetDriverObjectExtension(DriverObject, HwInitializationData->HwInitialize); 880 881 if (!driverExtension) 882 { 883 Status = IoAllocateDriverObjectExtension(DriverObject, 884 HwInitializationData->HwInitialize, 885 sizeof(SCSI_PORT_DRIVER_EXTENSION), 886 (PVOID *)&driverExtension); 887 888 if (!NT_SUCCESS(Status)) 889 { 890 DPRINT1("Failed to allocate the driver extension! Status 0x%x\n", Status); 891 return Status; 892 } 893 } 894 895 // set up the driver extension 896 driverExtension->RegistryPath.Buffer = 897 ExAllocatePoolWithTag(PagedPool, RegistryPath->MaximumLength, TAG_SCSIPORT); 898 driverExtension->RegistryPath.MaximumLength = RegistryPath->MaximumLength; 899 RtlCopyUnicodeString(&driverExtension->RegistryPath, RegistryPath); 900 901 driverExtension->DriverObject = DriverObject; 902 903 /* Set handlers */ 904 DriverObject->DriverUnload = ScsiPortUnload; 905 DriverObject->DriverStartIo = ScsiPortStartIo; 906 DriverObject->DriverExtension->AddDevice = ScsiPortAddDevice; 907 DriverObject->MajorFunction[IRP_MJ_CREATE] = ScsiPortCreateClose; 908 DriverObject->MajorFunction[IRP_MJ_CLOSE] = ScsiPortCreateClose; 909 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ScsiPortDeviceControl; 910 DriverObject->MajorFunction[IRP_MJ_SCSI] = ScsiPortDispatchScsi; 911 DriverObject->MajorFunction[IRP_MJ_PNP] = ScsiPortDispatchPnp; 912 DriverObject->MajorFunction[IRP_MJ_POWER] = ScsiPortDispatchPower; 913 914 /* Obtain configuration information */ 915 SystemConfig = IoGetConfigurationInformation(); 916 917 /* Zero the internal configuration info structure */ 918 RtlZeroMemory(&ConfigInfo, sizeof(CONFIGURATION_INFO)); 919 920 /* Zero starting slot number */ 921 SlotNumber.u.AsULONG = 0; 922 923 /* Allocate space for access ranges */ 924 if (HwInitializationData->NumberOfAccessRanges) 925 { 926 ConfigInfo.AccessRanges = 927 ExAllocatePoolWithTag(PagedPool, 928 HwInitializationData->NumberOfAccessRanges * sizeof(ACCESS_RANGE), TAG_SCSIPORT); 929 930 /* Fail if failed */ 931 if (ConfigInfo.AccessRanges == NULL) 932 return STATUS_INSUFFICIENT_RESOURCES; 933 } 934 935 /* Open registry keys and fill the driverExtension */ 936 SpiInitOpenKeys(&ConfigInfo, driverExtension); 937 938 // FIXME: PnP miniports are not supported 939 ASSERT(driverExtension->IsLegacyDriver); 940 941 /* Last adapter number = not known */ 942 ConfigInfo.LastAdapterNumber = SP_UNINITIALIZED_VALUE; 943 944 /* Calculate sizes of DeviceExtension and PortConfig */ 945 DeviceExtensionSize = sizeof(SCSI_PORT_DEVICE_EXTENSION) + 946 HwInitializationData->DeviceExtensionSize; 947 948 MaxBus = (HwInitializationData->AdapterInterfaceType == PCIBus) ? 8 : 1; 949 DPRINT("MaxBus: %lu\n", MaxBus); 950 951 while (TRUE) 952 { 953 WCHAR NameBuffer[27]; 954 /* Create a unicode device name */ 955 swprintf(NameBuffer, 956 L"\\Device\\ScsiPort%lu", 957 SystemConfig->ScsiPortCount); 958 if (!RtlCreateUnicodeString(&DeviceName, NameBuffer)) 959 { 960 DPRINT1("Failed to allocate memory for device name!\n"); 961 Status = STATUS_INSUFFICIENT_RESOURCES; 962 PortDeviceObject = NULL; 963 break; 964 } 965 966 DPRINT("Creating device: %wZ\n", &DeviceName); 967 968 /* Create the port device */ 969 Status = IoCreateDevice(DriverObject, 970 DeviceExtensionSize, 971 &DeviceName, 972 FILE_DEVICE_CONTROLLER, 973 FILE_DEVICE_SECURE_OPEN, 974 FALSE, 975 &PortDeviceObject); 976 977 if (!NT_SUCCESS(Status)) 978 { 979 DPRINT1("IoCreateDevice call failed! (Status 0x%lX)\n", Status); 980 PortDeviceObject = NULL; 981 break; 982 } 983 984 DPRINT1("Created device: %wZ (%p)\n", &DeviceName, PortDeviceObject); 985 986 /* Set the buffering strategy here... */ 987 PortDeviceObject->Flags |= DO_DIRECT_IO; 988 PortDeviceObject->AlignmentRequirement = FILE_WORD_ALIGNMENT; /* FIXME: Is this really needed? */ 989 990 /* Fill Device Extension */ 991 DeviceExtension = PortDeviceObject->DeviceExtension; 992 RtlZeroMemory(DeviceExtension, DeviceExtensionSize); 993 DeviceExtension->Common.DeviceObject = PortDeviceObject; 994 DeviceExtension->Common.IsFDO = TRUE; 995 DeviceExtension->Length = DeviceExtensionSize; 996 DeviceExtension->PortNumber = SystemConfig->ScsiPortCount; 997 DeviceExtension->DeviceName = DeviceName; 998 999 /* Driver's routines... */ 1000 DeviceExtension->HwInitialize = HwInitializationData->HwInitialize; 1001 DeviceExtension->HwStartIo = HwInitializationData->HwStartIo; 1002 DeviceExtension->HwInterrupt = HwInitializationData->HwInterrupt; 1003 DeviceExtension->HwResetBus = HwInitializationData->HwResetBus; 1004 DeviceExtension->HwDmaStarted = HwInitializationData->HwDmaStarted; 1005 1006 /* Extensions sizes */ 1007 DeviceExtension->MiniPortExtensionSize = HwInitializationData->DeviceExtensionSize; 1008 DeviceExtension->LunExtensionSize = 1009 ALIGN_UP(HwInitializationData->SpecificLuExtensionSize, INT64); 1010 DeviceExtension->SrbExtensionSize = 1011 ALIGN_UP(HwInitializationData->SrbExtensionSize, INT64); 1012 1013 /* Fill some numbers (bus count, lun count, etc) */ 1014 DeviceExtension->MaxLunCount = SCSI_MAXIMUM_LOGICAL_UNITS; 1015 DeviceExtension->RequestsNumber = 16; 1016 1017 /* Initialize the spin lock in the controller extension */ 1018 KeInitializeSpinLock(&DeviceExtension->IrqLock); 1019 KeInitializeSpinLock(&DeviceExtension->SpinLock); 1020 1021 /* Initialize the DPC object */ 1022 IoInitializeDpcRequest(PortDeviceObject, 1023 ScsiPortDpcForIsr); 1024 1025 /* Initialize the device timer */ 1026 DeviceExtension->TimerCount = -1; 1027 IoInitializeTimer(PortDeviceObject, 1028 ScsiPortIoTimer, 1029 DeviceExtension); 1030 1031 /* Initialize miniport timer */ 1032 KeInitializeTimer(&DeviceExtension->MiniportTimer); 1033 KeInitializeDpc(&DeviceExtension->MiniportTimerDpc, 1034 SpiMiniportTimerDpc, 1035 PortDeviceObject); 1036 1037 CreatePortConfig: 1038 1039 /* Allocate and initialize port configuration info */ 1040 PortConfigSize = sizeof(PORT_CONFIGURATION_INFORMATION) + 1041 HwInitializationData->NumberOfAccessRanges * sizeof(ACCESS_RANGE); 1042 PortConfigSize = ALIGN_UP(PortConfigSize, INT64); 1043 DeviceExtension->PortConfig = ExAllocatePoolWithTag(NonPagedPool, PortConfigSize, TAG_SCSIPORT); 1044 1045 /* Fail if failed */ 1046 if (DeviceExtension->PortConfig == NULL) 1047 { 1048 Status = STATUS_INSUFFICIENT_RESOURCES; 1049 break; 1050 } 1051 1052 Status = SpiCreatePortConfig(DeviceExtension, 1053 HwInitializationData, 1054 &ConfigInfo, 1055 DeviceExtension->PortConfig, 1056 FirstConfigCall); 1057 1058 if (!NT_SUCCESS(Status)) 1059 { 1060 DPRINT("SpiCreatePortConfig() failed with Status 0x%08X\n", Status); 1061 break; 1062 } 1063 1064 PortConfig = DeviceExtension->PortConfig; 1065 1066 /* Copy extension sizes into the PortConfig */ 1067 PortConfig->SpecificLuExtensionSize = DeviceExtension->LunExtensionSize; 1068 PortConfig->SrbExtensionSize = DeviceExtension->SrbExtensionSize; 1069 1070 /* Initialize Access ranges */ 1071 if (HwInitializationData->NumberOfAccessRanges != 0) 1072 { 1073 PortConfig->AccessRanges = ALIGN_UP_POINTER(PortConfig + 1, INT64); 1074 1075 /* Copy the data */ 1076 RtlCopyMemory(PortConfig->AccessRanges, 1077 ConfigInfo.AccessRanges, 1078 HwInitializationData->NumberOfAccessRanges * sizeof(ACCESS_RANGE)); 1079 } 1080 1081 /* Search for matching PCI device */ 1082 if ((HwInitializationData->AdapterInterfaceType == PCIBus) && 1083 (HwInitializationData->VendorIdLength > 0) && 1084 (HwInitializationData->VendorId != NULL) && 1085 (HwInitializationData->DeviceIdLength > 0) && (HwInitializationData->DeviceId != NULL)) 1086 { 1087 PortConfig->BusInterruptLevel = 0; 1088 1089 /* Get PCI device data */ 1090 DPRINT( 1091 "VendorId '%.*s' DeviceId '%.*s'\n", HwInitializationData->VendorIdLength, 1092 HwInitializationData->VendorId, HwInitializationData->DeviceIdLength, 1093 HwInitializationData->DeviceId); 1094 1095 if (!SpiGetPciConfigData( 1096 DriverObject, PortDeviceObject, HwInitializationData, PortConfig, RegistryPath, 1097 ConfigInfo.BusNumber, &SlotNumber)) 1098 { 1099 /* Continue to the next bus, nothing here */ 1100 ConfigInfo.BusNumber++; 1101 DeviceExtension->PortConfig = NULL; 1102 ExFreePool(PortConfig); 1103 Again = FALSE; 1104 goto CreatePortConfig; 1105 } 1106 1107 if (!PortConfig->BusInterruptLevel) 1108 { 1109 /* Bypass this slot, because no interrupt was assigned */ 1110 DeviceExtension->PortConfig = NULL; 1111 ExFreePool(PortConfig); 1112 goto CreatePortConfig; 1113 } 1114 } 1115 else 1116 { 1117 DPRINT("Non-pci bus\n"); 1118 } 1119 1120 /* Note: HwFindAdapter is called once for each bus */ 1121 Again = FALSE; 1122 DPRINT("Calling HwFindAdapter() for Bus %lu\n", PortConfig->SystemIoBusNumber); 1123 Result = (HwInitializationData->HwFindAdapter)( 1124 &DeviceExtension->MiniPortDeviceExtension, HwContext, 0, /* BusInformation */ 1125 ConfigInfo.Parameter, /* ArgumentString */ 1126 PortConfig, &Again); 1127 1128 DPRINT("HwFindAdapter() Result: %lu Again: %s\n", Result, (Again) ? "True" : "False"); 1129 1130 /* Free MapRegisterBase, it's not needed anymore */ 1131 if (DeviceExtension->MapRegisterBase != NULL) 1132 { 1133 ExFreePool(DeviceExtension->MapRegisterBase); 1134 DeviceExtension->MapRegisterBase = NULL; 1135 } 1136 1137 /* If result is nothing good... */ 1138 if (Result != SP_RETURN_FOUND) 1139 { 1140 DPRINT("HwFindAdapter() Result: %lu\n", Result); 1141 1142 if (Result == SP_RETURN_NOT_FOUND) 1143 { 1144 /* We can continue on the next bus */ 1145 ConfigInfo.BusNumber++; 1146 Again = FALSE; 1147 1148 DeviceExtension->PortConfig = NULL; 1149 ExFreePool(PortConfig); 1150 goto CreatePortConfig; 1151 } 1152 1153 /* Otherwise, break */ 1154 Status = STATUS_INTERNAL_ERROR; 1155 break; 1156 } 1157 1158 DPRINT( 1159 "ScsiPortInitialize(): Found HBA! (%x), adapter Id %d\n", 1160 PortConfig->BusInterruptVector, PortConfig->InitiatorBusId[0]); 1161 1162 /* If the SRB extension size was updated */ 1163 if (!DeviceExtension->NonCachedExtension && 1164 (PortConfig->SrbExtensionSize != DeviceExtension->SrbExtensionSize)) 1165 { 1166 /* Set it (rounding to LONGLONG again) */ 1167 DeviceExtension->SrbExtensionSize = ALIGN_UP(PortConfig->SrbExtensionSize, INT64); 1168 } 1169 1170 /* The same with LUN extension size */ 1171 if (PortConfig->SpecificLuExtensionSize != DeviceExtension->LunExtensionSize) 1172 DeviceExtension->LunExtensionSize = PortConfig->SpecificLuExtensionSize; 1173 1174 /* Construct a resource list */ 1175 ResourceList = SpiConfigToResource(DeviceExtension, PortConfig); 1176 1177 PDEVICE_OBJECT LowerPDO = NULL; 1178 1179 Status = IoReportDetectedDevice(DriverObject, 1180 HwInitializationData->AdapterInterfaceType, 1181 ConfigInfo.BusNumber, 1182 PortConfig->SlotNumber, 1183 ResourceList, 1184 NULL, 1185 TRUE, 1186 &LowerPDO); 1187 1188 if (!NT_SUCCESS(Status)) 1189 { 1190 DPRINT1("IoReportDetectedDevice failed. Status: 0x%x\n", Status); 1191 __debugbreak(); 1192 break; 1193 } 1194 1195 DeviceExtension->Common.LowerDevice = IoAttachDeviceToDeviceStack(PortDeviceObject, LowerPDO); 1196 1197 ASSERT(DeviceExtension->Common.LowerDevice); 1198 1199 PortDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; 1200 1201 if (ResourceList) 1202 { 1203 ExFreePoolWithTag(ResourceList, TAG_SCSIPORT); 1204 } 1205 1206 /* Copy all stuff which we ever need from PortConfig to the DeviceExtension */ 1207 if (PortConfig->MaximumNumberOfTargets > SCSI_MAXIMUM_TARGETS_PER_BUS) 1208 DeviceExtension->MaxTargedIds = SCSI_MAXIMUM_TARGETS_PER_BUS; 1209 else 1210 DeviceExtension->MaxTargedIds = PortConfig->MaximumNumberOfTargets; 1211 1212 DeviceExtension->NumberOfBuses = PortConfig->NumberOfBuses; 1213 DeviceExtension->CachesData = PortConfig->CachesData; 1214 DeviceExtension->ReceiveEvent = PortConfig->ReceiveEvent; 1215 DeviceExtension->SupportsTaggedQueuing = PortConfig->TaggedQueuing; 1216 DeviceExtension->MultipleReqsPerLun = PortConfig->MultipleRequestPerLu; 1217 1218 /* Initialize bus scanning information */ 1219 size_t BusConfigSize = DeviceExtension->NumberOfBuses * sizeof(*DeviceExtension->Buses); 1220 DeviceExtension->Buses = ExAllocatePoolZero(NonPagedPool, BusConfigSize, TAG_SCSIPORT); 1221 if (!DeviceExtension->Buses) 1222 { 1223 DPRINT1("Out of resources!\n"); 1224 Status = STATUS_INSUFFICIENT_RESOURCES; 1225 break; 1226 } 1227 1228 // initialize bus data 1229 for (UINT8 pathId = 0; pathId < DeviceExtension->NumberOfBuses; pathId++) 1230 { 1231 DeviceExtension->Buses[pathId].BusIdentifier = 1232 DeviceExtension->PortConfig->InitiatorBusId[pathId]; 1233 InitializeListHead(&DeviceExtension->Buses[pathId].LunsListHead); 1234 } 1235 1236 /* If something was disabled via registry - apply it */ 1237 if (ConfigInfo.DisableMultipleLun) 1238 DeviceExtension->MultipleReqsPerLun = PortConfig->MultipleRequestPerLu = FALSE; 1239 1240 if (ConfigInfo.DisableTaggedQueueing) 1241 DeviceExtension->SupportsTaggedQueuing = PortConfig->MultipleRequestPerLu = FALSE; 1242 1243 /* Check if we need to alloc SRB data */ 1244 if (DeviceExtension->SupportsTaggedQueuing || DeviceExtension->MultipleReqsPerLun) 1245 { 1246 DeviceExtension->NeedSrbDataAlloc = TRUE; 1247 } 1248 else 1249 { 1250 DeviceExtension->NeedSrbDataAlloc = FALSE; 1251 } 1252 1253 /* Get a pointer to the port capabilities */ 1254 PortCapabilities = &DeviceExtension->PortCapabilities; 1255 1256 /* Copy one field there */ 1257 DeviceExtension->MapBuffers = PortConfig->MapBuffers; 1258 PortCapabilities->AdapterUsesPio = PortConfig->MapBuffers; 1259 1260 if (DeviceExtension->AdapterObject == NULL && 1261 (PortConfig->DmaChannel != SP_UNINITIALIZED_VALUE || PortConfig->Master)) 1262 { 1263 DPRINT1("DMA is not supported yet\n"); 1264 ASSERT(FALSE); 1265 } 1266 1267 if (DeviceExtension->SrbExtensionBuffer == NULL && 1268 (DeviceExtension->SrbExtensionSize != 0 || PortConfig->AutoRequestSense)) 1269 { 1270 DeviceExtension->SupportsAutoSense = PortConfig->AutoRequestSense; 1271 DeviceExtension->NeedSrbExtensionAlloc = TRUE; 1272 1273 /* Allocate common buffer */ 1274 Status = SpiAllocateCommonBuffer(DeviceExtension, 0); 1275 1276 /* Check for failure */ 1277 if (!NT_SUCCESS(Status)) 1278 break; 1279 } 1280 1281 /* Allocate SrbData, if needed */ 1282 if (DeviceExtension->NeedSrbDataAlloc) 1283 { 1284 ULONG Count; 1285 PSCSI_REQUEST_BLOCK_INFO SrbData; 1286 1287 if (DeviceExtension->SrbDataCount != 0) 1288 Count = DeviceExtension->SrbDataCount; 1289 else 1290 Count = DeviceExtension->RequestsNumber * 2; 1291 1292 /* Allocate the data */ 1293 SrbData = ExAllocatePoolWithTag( 1294 NonPagedPool, Count * sizeof(SCSI_REQUEST_BLOCK_INFO), TAG_SCSIPORT); 1295 if (SrbData == NULL) 1296 return STATUS_INSUFFICIENT_RESOURCES; 1297 1298 RtlZeroMemory(SrbData, Count * sizeof(SCSI_REQUEST_BLOCK_INFO)); 1299 1300 DeviceExtension->SrbInfo = SrbData; 1301 DeviceExtension->FreeSrbInfo = SrbData; 1302 DeviceExtension->SrbDataCount = Count; 1303 1304 /* Link it to the list */ 1305 while (Count > 0) 1306 { 1307 SrbData->Requests.Flink = (PLIST_ENTRY)(SrbData + 1); 1308 SrbData++; 1309 Count--; 1310 } 1311 1312 /* Mark the last entry of the list */ 1313 SrbData--; 1314 SrbData->Requests.Flink = NULL; 1315 } 1316 1317 /* Initialize port capabilities */ 1318 PortCapabilities = &DeviceExtension->PortCapabilities; 1319 PortCapabilities->Length = sizeof(IO_SCSI_CAPABILITIES); 1320 PortCapabilities->MaximumTransferLength = PortConfig->MaximumTransferLength; 1321 1322 if (PortConfig->ReceiveEvent) 1323 PortCapabilities->SupportedAsynchronousEvents |= SRBEV_SCSI_ASYNC_NOTIFICATION; 1324 1325 PortCapabilities->TaggedQueuing = DeviceExtension->SupportsTaggedQueuing; 1326 PortCapabilities->AdapterScansDown = PortConfig->AdapterScansDown; 1327 1328 if (PortConfig->AlignmentMask > PortDeviceObject->AlignmentRequirement) 1329 PortDeviceObject->AlignmentRequirement = PortConfig->AlignmentMask; 1330 1331 PortCapabilities->AlignmentMask = PortDeviceObject->AlignmentRequirement; 1332 1333 if (PortCapabilities->MaximumPhysicalPages == 0) 1334 { 1335 PortCapabilities->MaximumPhysicalPages = 1336 BYTES_TO_PAGES(PortCapabilities->MaximumTransferLength); 1337 1338 /* Apply miniport's limits */ 1339 if (PortConfig->NumberOfPhysicalBreaks < PortCapabilities->MaximumPhysicalPages) 1340 { 1341 PortCapabilities->MaximumPhysicalPages = PortConfig->NumberOfPhysicalBreaks; 1342 } 1343 } 1344 1345 FdoCallHWInitialize(DeviceExtension); 1346 1347 Status = FdoStartAdapter(DeviceExtension); 1348 1349 if (!NT_SUCCESS(Status)) 1350 { 1351 DPRINT1("Failed to start the legacy adapter. Status 0x%x\n", Status); 1352 break; 1353 } 1354 1355 FdoScanAdapter(DeviceExtension); 1356 1357 FirstConfigCall = FALSE; 1358 1359 /* Increase adapter number and bus number respectively */ 1360 ConfigInfo.AdapterNumber++; 1361 1362 if (!Again) 1363 ConfigInfo.BusNumber++; 1364 1365 DPRINT("Bus: %lu MaxBus: %lu\n", ConfigInfo.BusNumber, MaxBus); 1366 1367 DeviceFound = TRUE; 1368 } 1369 1370 /* Clean up the mess */ 1371 if (!NT_SUCCESS(Status) && PortDeviceObject) 1372 { 1373 FdoRemoveAdapter(DeviceExtension); 1374 } 1375 1376 /* Close registry keys */ 1377 if (ConfigInfo.ServiceKey != NULL) 1378 ZwClose(ConfigInfo.ServiceKey); 1379 1380 if (ConfigInfo.DeviceKey != NULL) 1381 ZwClose(ConfigInfo.DeviceKey); 1382 1383 if (ConfigInfo.BusKey != NULL) 1384 ZwClose(ConfigInfo.BusKey); 1385 1386 if (ConfigInfo.AccessRanges != NULL) 1387 ExFreePool(ConfigInfo.AccessRanges); 1388 1389 if (ConfigInfo.Parameter != NULL) 1390 ExFreePool(ConfigInfo.Parameter); 1391 1392 DPRINT("ScsiPortInitialize() done, Status = 0x%08X, DeviceFound = %d!\n", 1393 Status, DeviceFound); 1394 1395 return (DeviceFound == FALSE) ? Status : STATUS_SUCCESS; 1396 } 1397 1398 /* 1399 * @unimplemented 1400 */ 1401 VOID NTAPI 1402 ScsiPortIoMapTransfer(IN PVOID HwDeviceExtension, 1403 IN PSCSI_REQUEST_BLOCK Srb, 1404 IN PVOID LogicalAddress, 1405 IN ULONG Length) 1406 { 1407 DPRINT1("ScsiPortIoMapTransfer()\n"); 1408 UNIMPLEMENTED; 1409 } 1410 1411 /* 1412 * @unimplemented 1413 */ 1414 VOID NTAPI 1415 ScsiPortLogError(IN PVOID HwDeviceExtension, 1416 IN PSCSI_REQUEST_BLOCK Srb OPTIONAL, 1417 IN UCHAR PathId, 1418 IN UCHAR TargetId, 1419 IN UCHAR Lun, 1420 IN ULONG ErrorCode, 1421 IN ULONG UniqueId) 1422 { 1423 //PSCSI_PORT_DEVICE_EXTENSION DeviceExtension; 1424 1425 DPRINT1("ScsiPortLogError() called\n"); 1426 DPRINT1("PathId: 0x%02x TargetId: 0x%02x Lun: 0x%02x ErrorCode: 0x%08lx UniqueId: 0x%08lx\n", 1427 PathId, TargetId, Lun, ErrorCode, UniqueId); 1428 1429 //DeviceExtension = CONTAINING_RECORD(HwDeviceExtension, SCSI_PORT_DEVICE_EXTENSION, MiniPortDeviceExtension); 1430 1431 1432 DPRINT("ScsiPortLogError() done\n"); 1433 } 1434 1435 /* 1436 * @implemented 1437 */ 1438 VOID NTAPI 1439 ScsiPortMoveMemory(OUT PVOID Destination, 1440 IN PVOID Source, 1441 IN ULONG Length) 1442 { 1443 RtlMoveMemory(Destination, 1444 Source, 1445 Length); 1446 } 1447 1448 1449 /* 1450 * @implemented 1451 */ 1452 VOID 1453 ScsiPortNotification(IN SCSI_NOTIFICATION_TYPE NotificationType, IN PVOID HwDeviceExtension, ...) 1454 { 1455 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension; 1456 va_list ap; 1457 1458 DPRINT("ScsiPortNotification() called\n"); 1459 1460 DeviceExtension = 1461 CONTAINING_RECORD(HwDeviceExtension, SCSI_PORT_DEVICE_EXTENSION, MiniPortDeviceExtension); 1462 1463 DPRINT("DeviceExtension %p\n", DeviceExtension); 1464 1465 va_start(ap, HwDeviceExtension); 1466 1467 switch (NotificationType) 1468 { 1469 case RequestComplete: 1470 { 1471 PSCSI_REQUEST_BLOCK Srb; 1472 PSCSI_REQUEST_BLOCK_INFO SrbData; 1473 1474 Srb = (PSCSI_REQUEST_BLOCK)va_arg(ap, PSCSI_REQUEST_BLOCK); 1475 1476 DPRINT("Notify: RequestComplete (Srb %p)\n", Srb); 1477 1478 /* Make sure Srb is alright */ 1479 ASSERT(Srb->SrbStatus != SRB_STATUS_PENDING); 1480 ASSERT( 1481 Srb->Function != SRB_FUNCTION_EXECUTE_SCSI || 1482 Srb->SrbStatus != SRB_STATUS_SUCCESS || Srb->ScsiStatus == SCSISTAT_GOOD); 1483 1484 if (!(Srb->SrbFlags & SRB_FLAGS_IS_ACTIVE)) 1485 { 1486 /* It's been already completed */ 1487 va_end(ap); 1488 return; 1489 } 1490 1491 /* It's not active anymore */ 1492 Srb->SrbFlags &= ~SRB_FLAGS_IS_ACTIVE; 1493 1494 if (Srb->Function == SRB_FUNCTION_ABORT_COMMAND) 1495 { 1496 /* TODO: Treat it specially */ 1497 ASSERT(FALSE); 1498 } 1499 else 1500 { 1501 PIO_STACK_LOCATION IoStack = IoGetCurrentIrpStackLocation(Srb->OriginalRequest); 1502 PSCSI_PORT_LUN_EXTENSION LunExtension = IoStack->DeviceObject->DeviceExtension; 1503 ASSERT(LunExtension && !LunExtension->Common.IsFDO); 1504 1505 /* Get the SRB data */ 1506 SrbData = SpiGetSrbData(DeviceExtension, LunExtension, Srb->QueueTag); 1507 1508 /* Make sure there are no CompletedRequests and there is a Srb */ 1509 ASSERT(SrbData->CompletedRequests == NULL && SrbData->Srb != NULL); 1510 1511 /* If it's a read/write request, make sure it has data inside it */ 1512 if ((Srb->SrbStatus == SRB_STATUS_SUCCESS) && 1513 ((Srb->Cdb[0] == SCSIOP_READ) || (Srb->Cdb[0] == SCSIOP_WRITE))) 1514 { 1515 ASSERT(Srb->DataTransferLength); 1516 } 1517 1518 SrbData->CompletedRequests = DeviceExtension->InterruptData.CompletedRequests; 1519 DeviceExtension->InterruptData.CompletedRequests = SrbData; 1520 } 1521 } 1522 break; 1523 1524 case NextRequest: 1525 DPRINT("Notify: NextRequest\n"); 1526 DeviceExtension->InterruptData.Flags |= SCSI_PORT_NEXT_REQUEST_READY; 1527 break; 1528 1529 case NextLuRequest: 1530 { 1531 UCHAR PathId; 1532 UCHAR TargetId; 1533 UCHAR Lun; 1534 PSCSI_PORT_LUN_EXTENSION LunExtension; 1535 1536 PathId = (UCHAR)va_arg(ap, int); 1537 TargetId = (UCHAR)va_arg(ap, int); 1538 Lun = (UCHAR)va_arg(ap, int); 1539 1540 DPRINT( 1541 "Notify: NextLuRequest(PathId %u TargetId %u Lun %u)\n", PathId, TargetId, Lun); 1542 1543 /* Mark it in the flags field */ 1544 DeviceExtension->InterruptData.Flags |= SCSI_PORT_NEXT_REQUEST_READY; 1545 1546 /* Get the LUN extension */ 1547 LunExtension = GetLunByPath(DeviceExtension, PathId, TargetId, Lun); 1548 1549 /* If returned LunExtension is NULL, break out */ 1550 if (!LunExtension) 1551 break; 1552 1553 /* This request should not be processed if */ 1554 if ((LunExtension->ReadyLun) || (LunExtension->SrbInfo.Srb)) 1555 { 1556 /* Nothing to do here */ 1557 break; 1558 } 1559 1560 /* Add this LUN to the list */ 1561 LunExtension->ReadyLun = DeviceExtension->InterruptData.ReadyLun; 1562 DeviceExtension->InterruptData.ReadyLun = LunExtension; 1563 } 1564 break; 1565 1566 case ResetDetected: 1567 DPRINT("Notify: ResetDetected\n"); 1568 /* Add RESET flags */ 1569 DeviceExtension->InterruptData.Flags |= SCSI_PORT_RESET | SCSI_PORT_RESET_REPORTED; 1570 break; 1571 1572 case CallDisableInterrupts: 1573 DPRINT1("UNIMPLEMENTED SCSI Notification called: CallDisableInterrupts!\n"); 1574 break; 1575 1576 case CallEnableInterrupts: 1577 DPRINT1("UNIMPLEMENTED SCSI Notification called: CallEnableInterrupts!\n"); 1578 break; 1579 1580 case RequestTimerCall: 1581 DPRINT("Notify: RequestTimerCall\n"); 1582 DeviceExtension->InterruptData.Flags |= SCSI_PORT_TIMER_NEEDED; 1583 DeviceExtension->InterruptData.HwScsiTimer = (PHW_TIMER)va_arg(ap, PHW_TIMER); 1584 DeviceExtension->InterruptData.MiniportTimerValue = (ULONG)va_arg(ap, ULONG); 1585 break; 1586 1587 case BusChangeDetected: 1588 DPRINT1("UNIMPLEMENTED SCSI Notification called: BusChangeDetected!\n"); 1589 break; 1590 1591 default: 1592 DPRINT1("Unsupported notification from WMI: %lu\n", NotificationType); 1593 break; 1594 } 1595 1596 va_end(ap); 1597 1598 /* Request a DPC after we're done with the interrupt */ 1599 DeviceExtension->InterruptData.Flags |= SCSI_PORT_NOTIFICATION_NEEDED; 1600 } 1601 1602 /* 1603 * @implemented 1604 */ 1605 BOOLEAN NTAPI 1606 ScsiPortValidateRange(IN PVOID HwDeviceExtension, 1607 IN INTERFACE_TYPE BusType, 1608 IN ULONG SystemIoBusNumber, 1609 IN SCSI_PHYSICAL_ADDRESS IoAddress, 1610 IN ULONG NumberOfBytes, 1611 IN BOOLEAN InIoSpace) 1612 { 1613 DPRINT("ScsiPortValidateRange()\n"); 1614 return(TRUE); 1615 } 1616 1617 1618 /* INTERNAL FUNCTIONS ********************************************************/ 1619 1620 static VOID 1621 SpiResourceToConfig(IN PHW_INITIALIZATION_DATA HwInitializationData, 1622 IN PCM_FULL_RESOURCE_DESCRIPTOR ResourceDescriptor, 1623 IN PPORT_CONFIGURATION_INFORMATION PortConfig) 1624 { 1625 PACCESS_RANGE AccessRange; 1626 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialData; 1627 ULONG RangeNumber; 1628 ULONG Index; 1629 ULONG Interrupt = 0; 1630 ULONG Dma = 0; 1631 1632 RangeNumber = 0; 1633 1634 /* Loop through all entries */ 1635 for (Index = 0; Index < ResourceDescriptor->PartialResourceList.Count; Index++) 1636 { 1637 PartialData = &ResourceDescriptor->PartialResourceList.PartialDescriptors[Index]; 1638 1639 switch (PartialData->Type) 1640 { 1641 case CmResourceTypePort: 1642 /* Copy access ranges */ 1643 if (RangeNumber < HwInitializationData->NumberOfAccessRanges) 1644 { 1645 AccessRange = &((*(PortConfig->AccessRanges))[RangeNumber]); 1646 1647 AccessRange->RangeStart = PartialData->u.Port.Start; 1648 AccessRange->RangeLength = PartialData->u.Port.Length; 1649 1650 AccessRange->RangeInMemory = FALSE; 1651 RangeNumber++; 1652 } 1653 break; 1654 1655 case CmResourceTypeMemory: 1656 /* Copy access ranges */ 1657 if (RangeNumber < HwInitializationData->NumberOfAccessRanges) 1658 { 1659 AccessRange = &((*(PortConfig->AccessRanges))[RangeNumber]); 1660 1661 AccessRange->RangeStart = PartialData->u.Memory.Start; 1662 AccessRange->RangeLength = PartialData->u.Memory.Length; 1663 1664 AccessRange->RangeInMemory = TRUE; 1665 RangeNumber++; 1666 } 1667 break; 1668 1669 case CmResourceTypeInterrupt: 1670 1671 if (Interrupt == 0) 1672 { 1673 /* Copy interrupt data */ 1674 PortConfig->BusInterruptLevel = PartialData->u.Interrupt.Level; 1675 PortConfig->BusInterruptVector = PartialData->u.Interrupt.Vector; 1676 1677 /* Set interrupt mode accordingly to the resource */ 1678 if (PartialData->Flags == CM_RESOURCE_INTERRUPT_LATCHED) 1679 { 1680 PortConfig->InterruptMode = Latched; 1681 } 1682 else if (PartialData->Flags == CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE) 1683 { 1684 PortConfig->InterruptMode = LevelSensitive; 1685 } 1686 } 1687 else if (Interrupt == 1) 1688 { 1689 /* Copy interrupt data */ 1690 PortConfig->BusInterruptLevel2 = PartialData->u.Interrupt.Level; 1691 PortConfig->BusInterruptVector2 = PartialData->u.Interrupt.Vector; 1692 1693 /* Set interrupt mode accordingly to the resource */ 1694 if (PartialData->Flags == CM_RESOURCE_INTERRUPT_LATCHED) 1695 { 1696 PortConfig->InterruptMode2 = Latched; 1697 } 1698 else if (PartialData->Flags == CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE) 1699 { 1700 PortConfig->InterruptMode2 = LevelSensitive; 1701 } 1702 } 1703 1704 Interrupt++; 1705 break; 1706 1707 case CmResourceTypeDma: 1708 1709 if (Dma == 0) 1710 { 1711 PortConfig->DmaChannel = PartialData->u.Dma.Channel; 1712 PortConfig->DmaPort = PartialData->u.Dma.Port; 1713 1714 if (PartialData->Flags & CM_RESOURCE_DMA_8) 1715 PortConfig->DmaWidth = Width8Bits; 1716 else if ((PartialData->Flags & CM_RESOURCE_DMA_16) || 1717 (PartialData->Flags & CM_RESOURCE_DMA_8_AND_16)) //??? 1718 PortConfig->DmaWidth = Width16Bits; 1719 else if (PartialData->Flags & CM_RESOURCE_DMA_32) 1720 PortConfig->DmaWidth = Width32Bits; 1721 } 1722 else if (Dma == 1) 1723 { 1724 PortConfig->DmaChannel2 = PartialData->u.Dma.Channel; 1725 PortConfig->DmaPort2 = PartialData->u.Dma.Port; 1726 1727 if (PartialData->Flags & CM_RESOURCE_DMA_8) 1728 PortConfig->DmaWidth2 = Width8Bits; 1729 else if ((PartialData->Flags & CM_RESOURCE_DMA_16) || 1730 (PartialData->Flags & CM_RESOURCE_DMA_8_AND_16)) //??? 1731 PortConfig->DmaWidth2 = Width16Bits; 1732 else if (PartialData->Flags & CM_RESOURCE_DMA_32) 1733 PortConfig->DmaWidth2 = Width32Bits; 1734 } 1735 break; 1736 } 1737 } 1738 } 1739 1740 static PCM_RESOURCE_LIST 1741 SpiConfigToResource(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension, 1742 PPORT_CONFIGURATION_INFORMATION PortConfig) 1743 { 1744 PCONFIGURATION_INFORMATION ConfigInfo; 1745 PCM_RESOURCE_LIST ResourceList; 1746 PCM_PARTIAL_RESOURCE_DESCRIPTOR ResourceDescriptor; 1747 PACCESS_RANGE AccessRange; 1748 ULONG ListLength = 0, i, FullSize; 1749 ULONG Interrupt, Dma; 1750 1751 /* Get current Atdisk usage from the system */ 1752 ConfigInfo = IoGetConfigurationInformation(); 1753 1754 if (PortConfig->AtdiskPrimaryClaimed) 1755 ConfigInfo->AtDiskPrimaryAddressClaimed = TRUE; 1756 1757 if (PortConfig->AtdiskSecondaryClaimed) 1758 ConfigInfo->AtDiskSecondaryAddressClaimed = TRUE; 1759 1760 /* Do we use DMA? */ 1761 if (PortConfig->DmaChannel != SP_UNINITIALIZED_VALUE || 1762 PortConfig->DmaPort != SP_UNINITIALIZED_VALUE) 1763 { 1764 Dma = 1; 1765 1766 if (PortConfig->DmaChannel2 != SP_UNINITIALIZED_VALUE || 1767 PortConfig->DmaPort2 != SP_UNINITIALIZED_VALUE) 1768 Dma++; 1769 } 1770 else 1771 { 1772 Dma = 0; 1773 } 1774 ListLength += Dma; 1775 1776 /* How many interrupts to we have? */ 1777 Interrupt = DeviceExtension->InterruptCount; 1778 ListLength += Interrupt; 1779 1780 /* How many access ranges do we use? */ 1781 AccessRange = &((*(PortConfig->AccessRanges))[0]); 1782 for (i = 0; i < PortConfig->NumberOfAccessRanges; i++) 1783 { 1784 if (AccessRange->RangeLength != 0) 1785 ListLength++; 1786 1787 AccessRange++; 1788 } 1789 1790 /* Allocate the resource list, since we know its size now */ 1791 FullSize = sizeof(CM_RESOURCE_LIST) + (ListLength - 1) * 1792 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR); 1793 1794 ResourceList = (PCM_RESOURCE_LIST)ExAllocatePoolWithTag(PagedPool, FullSize, TAG_SCSIPORT); 1795 1796 if (!ResourceList) 1797 return NULL; 1798 1799 /* Zero it */ 1800 RtlZeroMemory(ResourceList, FullSize); 1801 1802 /* Initialize it */ 1803 ResourceList->Count = 1; 1804 ResourceList->List[0].InterfaceType = PortConfig->AdapterInterfaceType; 1805 ResourceList->List[0].BusNumber = PortConfig->SystemIoBusNumber; 1806 ResourceList->List[0].PartialResourceList.Count = ListLength; 1807 ResourceDescriptor = ResourceList->List[0].PartialResourceList.PartialDescriptors; 1808 1809 /* Copy access ranges array over */ 1810 for (i = 0; i < PortConfig->NumberOfAccessRanges; i++) 1811 { 1812 AccessRange = &((*(PortConfig->AccessRanges))[i]); 1813 1814 /* If the range is empty - skip it */ 1815 if (AccessRange->RangeLength == 0) 1816 continue; 1817 1818 if (AccessRange->RangeInMemory) 1819 { 1820 ResourceDescriptor->Type = CmResourceTypeMemory; 1821 ResourceDescriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE; 1822 } 1823 else 1824 { 1825 ResourceDescriptor->Type = CmResourceTypePort; 1826 ResourceDescriptor->Flags = CM_RESOURCE_PORT_IO; 1827 } 1828 1829 ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive; 1830 1831 ResourceDescriptor->u.Memory.Start = AccessRange->RangeStart; 1832 ResourceDescriptor->u.Memory.Length = AccessRange->RangeLength; 1833 1834 ResourceDescriptor++; 1835 } 1836 1837 /* If we use interrupt(s), copy them */ 1838 while (Interrupt) 1839 { 1840 ResourceDescriptor->Type = CmResourceTypeInterrupt; 1841 1842 if (PortConfig->AdapterInterfaceType == MicroChannel || 1843 ((Interrupt == 2) ? PortConfig->InterruptMode2 : PortConfig->InterruptMode) == LevelSensitive) 1844 { 1845 ResourceDescriptor->ShareDisposition = CmResourceShareShared; 1846 ResourceDescriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE; 1847 } 1848 else 1849 { 1850 ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive; 1851 ResourceDescriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED; 1852 } 1853 1854 ResourceDescriptor->u.Interrupt.Level = (Interrupt == 2) ? PortConfig->BusInterruptLevel2 : PortConfig->BusInterruptLevel; 1855 ResourceDescriptor->u.Interrupt.Vector = (Interrupt == 2) ? PortConfig->BusInterruptVector2 : PortConfig->BusInterruptVector; 1856 ResourceDescriptor->u.Interrupt.Affinity = 0; 1857 1858 ResourceDescriptor++; 1859 Interrupt--; 1860 } 1861 1862 /* Copy DMA data */ 1863 while (Dma) 1864 { 1865 ResourceDescriptor->Type = CmResourceTypeDma; 1866 ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive; 1867 ResourceDescriptor->u.Dma.Channel = (Dma == 2) ? PortConfig->DmaChannel2 : PortConfig->DmaChannel; 1868 ResourceDescriptor->u.Dma.Port = (Dma == 2) ? PortConfig->DmaPort2 : PortConfig->DmaPort; 1869 ResourceDescriptor->Flags = 0; 1870 1871 if (((Dma == 2) ? PortConfig->DmaWidth2 : PortConfig->DmaWidth) == Width8Bits) 1872 ResourceDescriptor->Flags |= CM_RESOURCE_DMA_8; 1873 else if (((Dma == 2) ? PortConfig->DmaWidth2 : PortConfig->DmaWidth) == Width16Bits) 1874 ResourceDescriptor->Flags |= CM_RESOURCE_DMA_16; 1875 else 1876 ResourceDescriptor->Flags |= CM_RESOURCE_DMA_32; 1877 1878 if (((Dma == 2) ? PortConfig->DmaChannel2 : PortConfig->DmaChannel) == SP_UNINITIALIZED_VALUE) 1879 ResourceDescriptor->u.Dma.Channel = 0; 1880 1881 if (((Dma == 2) ? PortConfig->DmaPort2 : PortConfig->DmaPort) == SP_UNINITIALIZED_VALUE) 1882 ResourceDescriptor->u.Dma.Port = 0; 1883 1884 ResourceDescriptor++; 1885 Dma--; 1886 } 1887 1888 return ResourceList; 1889 } 1890 1891 1892 static BOOLEAN 1893 SpiGetPciConfigData(IN PDRIVER_OBJECT DriverObject, 1894 IN PDEVICE_OBJECT DeviceObject, 1895 IN struct _HW_INITIALIZATION_DATA *HwInitializationData, 1896 IN OUT PPORT_CONFIGURATION_INFORMATION PortConfig, 1897 IN PUNICODE_STRING RegistryPath, 1898 IN ULONG BusNumber, 1899 IN OUT PPCI_SLOT_NUMBER NextSlotNumber) 1900 { 1901 PCI_COMMON_CONFIG PciConfig; 1902 PCI_SLOT_NUMBER SlotNumber; 1903 ULONG DataSize; 1904 ULONG DeviceNumber; 1905 ULONG FunctionNumber; 1906 CHAR VendorIdString[8]; 1907 CHAR DeviceIdString[8]; 1908 UNICODE_STRING UnicodeStr; 1909 PCM_RESOURCE_LIST ResourceList = NULL; 1910 NTSTATUS Status; 1911 1912 DPRINT ("SpiGetPciConfiguration() called\n"); 1913 1914 SlotNumber.u.AsULONG = 0; 1915 1916 /* Loop through all devices */ 1917 for (DeviceNumber = NextSlotNumber->u.bits.DeviceNumber; DeviceNumber < PCI_MAX_DEVICES; DeviceNumber++) 1918 { 1919 SlotNumber.u.bits.DeviceNumber = DeviceNumber; 1920 1921 /* Loop through all functions */ 1922 for (FunctionNumber = NextSlotNumber->u.bits.FunctionNumber; FunctionNumber < PCI_MAX_FUNCTION; FunctionNumber++) 1923 { 1924 SlotNumber.u.bits.FunctionNumber = FunctionNumber; 1925 1926 /* Get PCI config bytes */ 1927 DataSize = HalGetBusData(PCIConfiguration, 1928 BusNumber, 1929 SlotNumber.u.AsULONG, 1930 &PciConfig, 1931 sizeof(ULONG)); 1932 1933 /* If result of HalGetBusData is 0, then the bus is wrong */ 1934 if (DataSize == 0) 1935 return FALSE; 1936 1937 /* Check if result is PCI_INVALID_VENDORID or too small */ 1938 if ((DataSize < sizeof(ULONG)) || 1939 (PciConfig.VendorID == PCI_INVALID_VENDORID)) 1940 { 1941 /* Continue to try the next function */ 1942 continue; 1943 } 1944 1945 sprintf (VendorIdString, "%04hx", PciConfig.VendorID); 1946 sprintf (DeviceIdString, "%04hx", PciConfig.DeviceID); 1947 1948 if (_strnicmp(VendorIdString, HwInitializationData->VendorId, HwInitializationData->VendorIdLength) || 1949 _strnicmp(DeviceIdString, HwInitializationData->DeviceId, HwInitializationData->DeviceIdLength)) 1950 { 1951 /* It is not our device */ 1952 continue; 1953 } 1954 1955 DPRINT("Found device 0x%04hx 0x%04hx at %1lu %2lu %1lu\n", 1956 PciConfig.VendorID, 1957 PciConfig.DeviceID, 1958 BusNumber, 1959 SlotNumber.u.bits.DeviceNumber, 1960 SlotNumber.u.bits.FunctionNumber); 1961 1962 1963 RtlInitUnicodeString(&UnicodeStr, L"ScsiAdapter"); 1964 Status = HalAssignSlotResources(RegistryPath, 1965 &UnicodeStr, 1966 DriverObject, 1967 DeviceObject, 1968 PCIBus, 1969 BusNumber, 1970 SlotNumber.u.AsULONG, 1971 &ResourceList); 1972 1973 if (!NT_SUCCESS(Status)) 1974 break; 1975 1976 /* Create configuration information */ 1977 SpiResourceToConfig(HwInitializationData, 1978 ResourceList->List, 1979 PortConfig); 1980 1981 /* Free the resource list */ 1982 ExFreePool(ResourceList); 1983 1984 /* Set dev & fn numbers */ 1985 NextSlotNumber->u.bits.DeviceNumber = DeviceNumber; 1986 NextSlotNumber->u.bits.FunctionNumber = FunctionNumber + 1; 1987 1988 /* Save the slot number */ 1989 PortConfig->SlotNumber = SlotNumber.u.AsULONG; 1990 1991 return TRUE; 1992 } 1993 NextSlotNumber->u.bits.FunctionNumber = 0; 1994 } 1995 1996 NextSlotNumber->u.bits.DeviceNumber = 0; 1997 DPRINT ("No device found\n"); 1998 1999 return FALSE; 2000 } 2001 2002 2003 2004 /********************************************************************** 2005 * NAME INTERNAL 2006 * ScsiPortCreateClose 2007 * 2008 * DESCRIPTION 2009 * Answer requests for Create/Close calls: a null operation. 2010 * 2011 * RUN LEVEL 2012 * PASSIVE_LEVEL 2013 * 2014 * ARGUMENTS 2015 * DeviceObject 2016 * Pointer to a device object. 2017 * 2018 * Irp 2019 * Pointer to an IRP. 2020 * 2021 * RETURN VALUE 2022 * Status. 2023 */ 2024 2025 static NTSTATUS NTAPI 2026 ScsiPortCreateClose(IN PDEVICE_OBJECT DeviceObject, 2027 IN PIRP Irp) 2028 { 2029 DPRINT("ScsiPortCreateClose()\n"); 2030 2031 Irp->IoStatus.Status = STATUS_SUCCESS; 2032 IoCompleteRequest(Irp, IO_NO_INCREMENT); 2033 2034 return STATUS_SUCCESS; 2035 } 2036 2037 IO_ALLOCATION_ACTION 2038 NTAPI 2039 SpiAdapterControl(PDEVICE_OBJECT DeviceObject, 2040 PIRP Irp, 2041 PVOID MapRegisterBase, 2042 PVOID Context) 2043 { 2044 PSCSI_REQUEST_BLOCK Srb; 2045 PSCSI_SG_ADDRESS ScatterGatherList; 2046 KIRQL CurrentIrql; 2047 PIO_STACK_LOCATION IrpStack; 2048 ULONG TotalLength = 0; 2049 PSCSI_REQUEST_BLOCK_INFO SrbInfo; 2050 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension; 2051 PUCHAR DataVA; 2052 BOOLEAN WriteToDevice; 2053 2054 /* Get pointers to SrbInfo and DeviceExtension */ 2055 SrbInfo = (PSCSI_REQUEST_BLOCK_INFO)Context; 2056 DeviceExtension = DeviceObject->DeviceExtension; 2057 2058 /* Get pointer to SRB */ 2059 IrpStack = IoGetCurrentIrpStackLocation(Irp); 2060 Srb = (PSCSI_REQUEST_BLOCK)IrpStack->Parameters.Others.Argument1; 2061 2062 /* Depending on the map registers number, we allocate 2063 either from NonPagedPool, or from our static list */ 2064 if (SrbInfo->NumberOfMapRegisters > MAX_SG_LIST) 2065 { 2066 SrbInfo->ScatterGather = ExAllocatePoolWithTag( 2067 NonPagedPool, SrbInfo->NumberOfMapRegisters * sizeof(SCSI_SG_ADDRESS), TAG_SCSIPORT); 2068 2069 if (SrbInfo->ScatterGather == NULL) 2070 ASSERT(FALSE); 2071 2072 Srb->SrbFlags |= SRB_FLAGS_SGLIST_FROM_POOL; 2073 } 2074 else 2075 { 2076 SrbInfo->ScatterGather = SrbInfo->ScatterGatherList; 2077 } 2078 2079 /* Use chosen SG list source */ 2080 ScatterGatherList = SrbInfo->ScatterGather; 2081 2082 /* Save map registers base */ 2083 SrbInfo->BaseOfMapRegister = MapRegisterBase; 2084 2085 /* Determine WriteToDevice flag */ 2086 WriteToDevice = Srb->SrbFlags & SRB_FLAGS_DATA_OUT ? TRUE : FALSE; 2087 2088 /* Get virtual address of the data buffer */ 2089 DataVA = (PUCHAR)MmGetMdlVirtualAddress(Irp->MdlAddress) + 2090 ((PCHAR)Srb->DataBuffer - SrbInfo->DataOffset); 2091 2092 /* Build the actual SG list */ 2093 while (TotalLength < Srb->DataTransferLength) 2094 { 2095 if (!ScatterGatherList) 2096 break; 2097 2098 ScatterGatherList->Length = Srb->DataTransferLength - TotalLength; 2099 ScatterGatherList->PhysicalAddress = IoMapTransfer(DeviceExtension->AdapterObject, 2100 Irp->MdlAddress, 2101 MapRegisterBase, 2102 DataVA + TotalLength, 2103 &ScatterGatherList->Length, 2104 WriteToDevice); 2105 2106 TotalLength += ScatterGatherList->Length; 2107 ScatterGatherList++; 2108 } 2109 2110 /* Schedule an active request */ 2111 InterlockedIncrement(&DeviceExtension->ActiveRequestCounter ); 2112 KeAcquireSpinLock(&DeviceExtension->SpinLock, &CurrentIrql); 2113 KeSynchronizeExecution(DeviceExtension->Interrupt[0], 2114 ScsiPortStartPacket, 2115 DeviceObject); 2116 KeReleaseSpinLock(&DeviceExtension->SpinLock, CurrentIrql); 2117 2118 return DeallocateObjectKeepRegisters; 2119 } 2120 2121 BOOLEAN 2122 NTAPI 2123 ScsiPortIsr( 2124 _In_ PKINTERRUPT Interrupt, 2125 _In_ PVOID ServiceContext) 2126 { 2127 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension; 2128 2129 DPRINT("ScsiPortIsr() called!\n"); 2130 2131 DeviceExtension = (PSCSI_PORT_DEVICE_EXTENSION)ServiceContext; 2132 2133 /* If interrupts are disabled - we don't expect any */ 2134 if (DeviceExtension->InterruptData.Flags & SCSI_PORT_DISABLE_INTERRUPTS) 2135 return FALSE; 2136 2137 /* Call miniport's HwInterrupt routine */ 2138 if (DeviceExtension->HwInterrupt(&DeviceExtension->MiniPortDeviceExtension) == FALSE) 2139 { 2140 /* This interrupt doesn't belong to us */ 2141 return FALSE; 2142 } 2143 2144 /* If flag of notification is set - queue a DPC */ 2145 if (DeviceExtension->InterruptData.Flags & SCSI_PORT_NOTIFICATION_NEEDED) 2146 { 2147 IoRequestDpc(DeviceExtension->Common.DeviceObject, 2148 DeviceExtension->CurrentIrp, 2149 DeviceExtension); 2150 } 2151 2152 return TRUE; 2153 } 2154 2155 BOOLEAN 2156 NTAPI 2157 SpiProcessTimeout(PVOID ServiceContext) 2158 { 2159 PDEVICE_OBJECT DeviceObject = (PDEVICE_OBJECT)ServiceContext; 2160 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension; 2161 ULONG Bus; 2162 2163 DPRINT("SpiProcessTimeout() entered\n"); 2164 2165 DeviceExtension->TimerCount = -1; 2166 2167 if (DeviceExtension->InterruptData.Flags & SCSI_PORT_RESET) 2168 { 2169 DeviceExtension->InterruptData.Flags &= ~SCSI_PORT_RESET; 2170 2171 if (DeviceExtension->InterruptData.Flags & SCSI_PORT_RESET_REQUEST) 2172 { 2173 DeviceExtension->InterruptData.Flags &= ~SCSI_PORT_RESET_REQUEST; 2174 ScsiPortStartPacket(ServiceContext); 2175 } 2176 2177 return FALSE; 2178 } 2179 else 2180 { 2181 DPRINT("Resetting the bus\n"); 2182 2183 for (Bus = 0; Bus < DeviceExtension->NumberOfBuses; Bus++) 2184 { 2185 DeviceExtension->HwResetBus(DeviceExtension->MiniPortDeviceExtension, Bus); 2186 2187 /* Reset flags and set reset timeout to 4 seconds */ 2188 DeviceExtension->InterruptData.Flags |= SCSI_PORT_RESET; 2189 DeviceExtension->TimerCount = 4; 2190 } 2191 2192 /* If miniport requested - request a dpc for it */ 2193 if (DeviceExtension->InterruptData.Flags & SCSI_PORT_NOTIFICATION_NEEDED) 2194 IoRequestDpc(DeviceExtension->Common.DeviceObject, NULL, NULL); 2195 } 2196 2197 return TRUE; 2198 } 2199 2200 2201 BOOLEAN 2202 NTAPI 2203 SpiResetBus(PVOID ServiceContext) 2204 { 2205 PRESETBUS_PARAMS ResetParams = (PRESETBUS_PARAMS)ServiceContext; 2206 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension; 2207 2208 /* Perform the bus reset */ 2209 DeviceExtension = (PSCSI_PORT_DEVICE_EXTENSION)ResetParams->DeviceExtension; 2210 DeviceExtension->HwResetBus(DeviceExtension->MiniPortDeviceExtension, 2211 ResetParams->PathId); 2212 2213 /* Set flags and start the timer */ 2214 DeviceExtension->InterruptData.Flags |= SCSI_PORT_RESET; 2215 DeviceExtension->TimerCount = 4; 2216 2217 /* If miniport requested - give him a DPC */ 2218 if (DeviceExtension->InterruptData.Flags & SCSI_PORT_NOTIFICATION_NEEDED) 2219 IoRequestDpc(DeviceExtension->Common.DeviceObject, NULL, NULL); 2220 2221 return TRUE; 2222 } 2223 2224 // ScsiPortIoTimer 2225 // DESCRIPTION: 2226 // This function handles timeouts and other time delayed processing 2227 // 2228 // RUN LEVEL: 2229 // 2230 // ARGUMENTS: 2231 // IN PDEVICE_OBJECT DeviceObject Device object registered with timer 2232 // IN PVOID Context the Controller extension for the 2233 // controller the device is on 2234 // 2235 static VOID NTAPI 2236 ScsiPortIoTimer(PDEVICE_OBJECT DeviceObject, 2237 PVOID Context) 2238 { 2239 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension; 2240 PSCSI_PORT_LUN_EXTENSION LunExtension; 2241 PIRP Irp; 2242 2243 DPRINT("ScsiPortIoTimer()\n"); 2244 2245 DeviceExtension = (PSCSI_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 2246 2247 /* Protect with the spinlock */ 2248 KeAcquireSpinLockAtDpcLevel(&DeviceExtension->SpinLock); 2249 2250 /* Check timeouts */ 2251 if (DeviceExtension->TimerCount > 0) 2252 { 2253 /* Decrease the timeout counter */ 2254 DeviceExtension->TimerCount--; 2255 2256 if (DeviceExtension->TimerCount == 0) 2257 { 2258 /* Timeout, process it */ 2259 if (KeSynchronizeExecution(DeviceExtension->Interrupt[0], 2260 SpiProcessTimeout, 2261 DeviceExtension->Common.DeviceObject)) 2262 { 2263 DPRINT("Error happened during processing timeout, but nothing critical\n"); 2264 } 2265 } 2266 2267 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock); 2268 2269 /* We should exit now, since timeout is processed */ 2270 return; 2271 } 2272 2273 /* Per-Lun scanning of timeouts is needed... */ 2274 for (UINT8 pathId = 0; pathId < DeviceExtension->NumberOfBuses; pathId++) 2275 { 2276 PSCSI_BUS_INFO bus = &DeviceExtension->Buses[pathId]; 2277 2278 for (PLIST_ENTRY lunEntry = bus->LunsListHead.Flink; 2279 lunEntry != &bus->LunsListHead; 2280 lunEntry = lunEntry->Flink) 2281 { 2282 LunExtension = CONTAINING_RECORD(lunEntry, SCSI_PORT_LUN_EXTENSION, LunEntry); 2283 2284 if (LunExtension->Flags & LUNEX_BUSY) 2285 { 2286 if (!(LunExtension->Flags & 2287 (LUNEX_NEED_REQUEST_SENSE | LUNEX_FROZEN_QUEUE))) 2288 { 2289 DPRINT("Retrying busy request\n"); 2290 2291 /* Clear flags, and retry busy request */ 2292 LunExtension->Flags &= ~(LUNEX_BUSY | LUNEX_FULL_QUEUE); 2293 Irp = LunExtension->BusyRequest; 2294 2295 /* Clearing busy request */ 2296 LunExtension->BusyRequest = NULL; 2297 2298 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock); 2299 2300 IoStartPacket(DeviceObject, Irp, (PULONG)NULL, NULL); 2301 2302 KeAcquireSpinLockAtDpcLevel(&DeviceExtension->SpinLock); 2303 } 2304 } 2305 else if (LunExtension->RequestTimeout == 0) 2306 { 2307 RESETBUS_PARAMS ResetParams; 2308 2309 LunExtension->RequestTimeout = -1; 2310 2311 DPRINT("Request timed out, resetting bus\n"); 2312 2313 /* Pass params to the bus reset routine */ 2314 ResetParams.PathId = LunExtension->PathId; 2315 ResetParams.DeviceExtension = DeviceExtension; 2316 2317 if (!KeSynchronizeExecution(DeviceExtension->Interrupt[0], 2318 SpiResetBus, 2319 &ResetParams)) 2320 { 2321 DPRINT1("Reset failed\n"); 2322 } 2323 } 2324 else if (LunExtension->RequestTimeout > 0) 2325 { 2326 /* Decrement the timeout counter */ 2327 LunExtension->RequestTimeout--; 2328 } 2329 } 2330 } 2331 2332 /* Release the spinlock */ 2333 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock); 2334 } 2335 2336 VOID 2337 NTAPI 2338 SpiMiniportTimerDpc(IN struct _KDPC *Dpc, 2339 IN PVOID DeviceObject, 2340 IN PVOID SystemArgument1, 2341 IN PVOID SystemArgument2) 2342 { 2343 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension; 2344 2345 DPRINT("Miniport timer DPC\n"); 2346 2347 DeviceExtension = ((PDEVICE_OBJECT)DeviceObject)->DeviceExtension; 2348 2349 /* Acquire the spinlock */ 2350 KeAcquireSpinLockAtDpcLevel(&DeviceExtension->SpinLock); 2351 2352 /* Call the timer routine */ 2353 if (DeviceExtension->HwScsiTimer != NULL) 2354 { 2355 DeviceExtension->HwScsiTimer(&DeviceExtension->MiniPortDeviceExtension); 2356 } 2357 2358 /* Release the spinlock */ 2359 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock); 2360 2361 if (DeviceExtension->InterruptData.Flags & SCSI_PORT_NOTIFICATION_NEEDED) 2362 { 2363 ScsiPortDpcForIsr(NULL, 2364 DeviceExtension->Common.DeviceObject, 2365 NULL, 2366 NULL); 2367 } 2368 } 2369 2370 static NTSTATUS 2371 SpiCreatePortConfig(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension, 2372 PHW_INITIALIZATION_DATA HwInitData, 2373 PCONFIGURATION_INFO InternalConfigInfo, 2374 PPORT_CONFIGURATION_INFORMATION ConfigInfo, 2375 BOOLEAN ZeroStruct) 2376 { 2377 UNICODE_STRING UnicodeString; 2378 OBJECT_ATTRIBUTES ObjectAttributes; 2379 PCONFIGURATION_INFORMATION DdkConfigInformation; 2380 HANDLE RootKey, Key; 2381 BOOLEAN Found; 2382 WCHAR DeviceBuffer[16]; 2383 WCHAR StrBuffer[512]; 2384 ULONG Bus; 2385 NTSTATUS Status; 2386 2387 /* Zero out the struct if told so */ 2388 if (ZeroStruct) 2389 { 2390 /* First zero the portconfig */ 2391 RtlZeroMemory(ConfigInfo, sizeof(PORT_CONFIGURATION_INFORMATION)); 2392 2393 /* Then access ranges */ 2394 RtlZeroMemory(InternalConfigInfo->AccessRanges, 2395 HwInitData->NumberOfAccessRanges * sizeof(ACCESS_RANGE)); 2396 2397 /* Initialize the struct */ 2398 ConfigInfo->Length = sizeof(PORT_CONFIGURATION_INFORMATION); 2399 ConfigInfo->AdapterInterfaceType = HwInitData->AdapterInterfaceType; 2400 ConfigInfo->InterruptMode = Latched; 2401 ConfigInfo->DmaChannel = SP_UNINITIALIZED_VALUE; 2402 ConfigInfo->DmaPort = SP_UNINITIALIZED_VALUE; 2403 ConfigInfo->DmaChannel2 = SP_UNINITIALIZED_VALUE; 2404 ConfigInfo->DmaPort2 = SP_UNINITIALIZED_VALUE; 2405 ConfigInfo->MaximumTransferLength = SP_UNINITIALIZED_VALUE; 2406 ConfigInfo->NumberOfAccessRanges = HwInitData->NumberOfAccessRanges; 2407 ConfigInfo->MaximumNumberOfTargets = 8; 2408 2409 /* Store parameters */ 2410 ConfigInfo->NeedPhysicalAddresses = HwInitData->NeedPhysicalAddresses; 2411 ConfigInfo->MapBuffers = HwInitData->MapBuffers; 2412 ConfigInfo->AutoRequestSense = HwInitData->AutoRequestSense; 2413 ConfigInfo->ReceiveEvent = HwInitData->ReceiveEvent; 2414 ConfigInfo->TaggedQueuing = HwInitData->TaggedQueuing; 2415 ConfigInfo->MultipleRequestPerLu = HwInitData->MultipleRequestPerLu; 2416 2417 /* Get the disk usage */ 2418 DdkConfigInformation = IoGetConfigurationInformation(); 2419 ConfigInfo->AtdiskPrimaryClaimed = DdkConfigInformation->AtDiskPrimaryAddressClaimed; 2420 ConfigInfo->AtdiskSecondaryClaimed = DdkConfigInformation->AtDiskSecondaryAddressClaimed; 2421 2422 /* Initiator bus id is not set */ 2423 for (Bus = 0; Bus < 8; Bus++) 2424 ConfigInfo->InitiatorBusId[Bus] = (CCHAR)SP_UNINITIALIZED_VALUE; 2425 } 2426 2427 ConfigInfo->NumberOfPhysicalBreaks = 17; 2428 2429 /* Clear this information */ 2430 InternalConfigInfo->DisableTaggedQueueing = FALSE; 2431 InternalConfigInfo->DisableMultipleLun = FALSE; 2432 2433 /* Store Bus Number */ 2434 ConfigInfo->SystemIoBusNumber = InternalConfigInfo->BusNumber; 2435 2436 TryNextAd: 2437 2438 if (ConfigInfo->AdapterInterfaceType == Internal) 2439 { 2440 /* Open registry key for HW database */ 2441 InitializeObjectAttributes(&ObjectAttributes, 2442 DeviceExtension->Common.DeviceObject->DriverObject->HardwareDatabase, 2443 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 2444 NULL, 2445 NULL); 2446 2447 Status = ZwOpenKey(&RootKey, 2448 KEY_READ, 2449 &ObjectAttributes); 2450 2451 if (NT_SUCCESS(Status)) 2452 { 2453 /* Create name for it */ 2454 swprintf(StrBuffer, L"ScsiAdapter\\%lu", 2455 InternalConfigInfo->AdapterNumber); 2456 2457 RtlInitUnicodeString(&UnicodeString, StrBuffer); 2458 2459 /* Open device key */ 2460 InitializeObjectAttributes(&ObjectAttributes, 2461 &UnicodeString, 2462 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 2463 RootKey, 2464 NULL); 2465 2466 Status = ZwOpenKey(&Key, 2467 KEY_READ, 2468 &ObjectAttributes); 2469 2470 ZwClose(RootKey); 2471 2472 if (NT_SUCCESS(Status)) 2473 { 2474 if (InternalConfigInfo->LastAdapterNumber != InternalConfigInfo->AdapterNumber) 2475 { 2476 DPRINT("Hardware info found at %S\n", StrBuffer); 2477 2478 /* Parse it */ 2479 SpiParseDeviceInfo(DeviceExtension, 2480 Key, 2481 ConfigInfo, 2482 InternalConfigInfo, 2483 (PUCHAR)StrBuffer); 2484 2485 InternalConfigInfo->BusNumber = 0; 2486 } 2487 else 2488 { 2489 /* Try the next adapter */ 2490 InternalConfigInfo->AdapterNumber++; 2491 goto TryNextAd; 2492 } 2493 } 2494 else 2495 { 2496 /* Info was not found, exit */ 2497 DPRINT1("ZwOpenKey() failed with Status=0x%08X\n", Status); 2498 return STATUS_DEVICE_DOES_NOT_EXIST; 2499 } 2500 } 2501 else 2502 { 2503 DPRINT1("ZwOpenKey() failed with Status=0x%08X\n", Status); 2504 } 2505 } 2506 2507 /* Look at device params */ 2508 Key = NULL; 2509 if (InternalConfigInfo->Parameter) 2510 { 2511 ExFreePool(InternalConfigInfo->Parameter); 2512 InternalConfigInfo->Parameter = NULL; 2513 } 2514 2515 if (InternalConfigInfo->ServiceKey != NULL) 2516 { 2517 swprintf(DeviceBuffer, L"Device%lu", InternalConfigInfo->AdapterNumber); 2518 RtlInitUnicodeString(&UnicodeString, DeviceBuffer); 2519 2520 /* Open the service key */ 2521 InitializeObjectAttributes(&ObjectAttributes, 2522 &UnicodeString, 2523 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 2524 InternalConfigInfo->ServiceKey, 2525 NULL); 2526 2527 Status = ZwOpenKey(&Key, 2528 KEY_READ, 2529 &ObjectAttributes); 2530 } 2531 2532 /* Parse device key */ 2533 if (InternalConfigInfo->DeviceKey != NULL) 2534 { 2535 SpiParseDeviceInfo(DeviceExtension, 2536 InternalConfigInfo->DeviceKey, 2537 ConfigInfo, 2538 InternalConfigInfo, 2539 (PUCHAR)StrBuffer); 2540 } 2541 2542 /* Then parse hw info */ 2543 if (Key != NULL) 2544 { 2545 if (InternalConfigInfo->LastAdapterNumber != InternalConfigInfo->AdapterNumber) 2546 { 2547 SpiParseDeviceInfo(DeviceExtension, 2548 Key, 2549 ConfigInfo, 2550 InternalConfigInfo, 2551 (PUCHAR)StrBuffer); 2552 2553 /* Close the key */ 2554 ZwClose(Key); 2555 } 2556 else 2557 { 2558 /* Adapter not found, go try the next one */ 2559 InternalConfigInfo->AdapterNumber++; 2560 2561 /* Close the key */ 2562 ZwClose(Key); 2563 2564 goto TryNextAd; 2565 } 2566 } 2567 2568 /* Update the last adapter number */ 2569 InternalConfigInfo->LastAdapterNumber = InternalConfigInfo->AdapterNumber; 2570 2571 /* Do we have this kind of bus at all? */ 2572 Found = FALSE; 2573 Status = IoQueryDeviceDescription(&HwInitData->AdapterInterfaceType, 2574 &InternalConfigInfo->BusNumber, 2575 NULL, 2576 NULL, 2577 NULL, 2578 NULL, 2579 SpQueryDeviceCallout, 2580 &Found); 2581 2582 /* This bus was not found */ 2583 if (!Found) 2584 { 2585 INTERFACE_TYPE InterfaceType = Eisa; 2586 2587 /* Check for EISA */ 2588 if (HwInitData->AdapterInterfaceType == Isa) 2589 { 2590 Status = IoQueryDeviceDescription(&InterfaceType, 2591 &InternalConfigInfo->BusNumber, 2592 NULL, 2593 NULL, 2594 NULL, 2595 NULL, 2596 SpQueryDeviceCallout, 2597 &Found); 2598 2599 /* Return respectively */ 2600 if (Found) 2601 return STATUS_SUCCESS; 2602 else 2603 return STATUS_DEVICE_DOES_NOT_EXIST; 2604 } 2605 else 2606 { 2607 return STATUS_DEVICE_DOES_NOT_EXIST; 2608 } 2609 } 2610 else 2611 { 2612 return STATUS_SUCCESS; 2613 } 2614 } 2615 2616 static VOID 2617 SpiParseDeviceInfo(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension, 2618 IN HANDLE Key, 2619 IN PPORT_CONFIGURATION_INFORMATION ConfigInfo, 2620 IN PCONFIGURATION_INFO InternalConfigInfo, 2621 IN PUCHAR Buffer) 2622 { 2623 PKEY_VALUE_FULL_INFORMATION KeyValueInformation; 2624 PCM_FULL_RESOURCE_DESCRIPTOR FullResource; 2625 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor; 2626 PCM_SCSI_DEVICE_DATA ScsiDeviceData; 2627 ULONG Length, Count, Dma = 0, Interrupt = 0; 2628 ULONG Index = 0, RangeCount = 0; 2629 UNICODE_STRING UnicodeString; 2630 ANSI_STRING AnsiString; 2631 NTSTATUS Status = STATUS_SUCCESS; 2632 2633 2634 KeyValueInformation = (PKEY_VALUE_FULL_INFORMATION) Buffer; 2635 2636 /* Loop through all values in the device node */ 2637 while(TRUE) 2638 { 2639 Status = ZwEnumerateValueKey(Key, 2640 Index, 2641 KeyValueFullInformation, 2642 Buffer, 2643 512, 2644 &Length); 2645 2646 if (!NT_SUCCESS(Status)) 2647 return; 2648 2649 Index++; 2650 2651 /* Length for DWORD is ok? */ 2652 if (KeyValueInformation->Type == REG_DWORD && 2653 KeyValueInformation->DataLength != sizeof(ULONG)) 2654 { 2655 continue; 2656 } 2657 2658 /* Get MaximumLogicalUnit */ 2659 if (_wcsnicmp(KeyValueInformation->Name, L"MaximumLogicalUnit", 2660 KeyValueInformation->NameLength/2) == 0) 2661 { 2662 2663 if (KeyValueInformation->Type != REG_DWORD) 2664 { 2665 DPRINT("Bad data type for MaximumLogicalUnit\n"); 2666 continue; 2667 } 2668 2669 DeviceExtension->MaxLunCount = *((PUCHAR) 2670 (Buffer + KeyValueInformation->DataOffset)); 2671 2672 /* Check / reset if needed */ 2673 if (DeviceExtension->MaxLunCount > SCSI_MAXIMUM_LOGICAL_UNITS) 2674 DeviceExtension->MaxLunCount = SCSI_MAXIMUM_LOGICAL_UNITS; 2675 2676 DPRINT("MaximumLogicalUnit = %d\n", DeviceExtension->MaxLunCount); 2677 } 2678 2679 /* Get InitiatorTargetId */ 2680 if (_wcsnicmp(KeyValueInformation->Name, L"InitiatorTargetId", 2681 KeyValueInformation->NameLength / 2) == 0) 2682 { 2683 2684 if (KeyValueInformation->Type != REG_DWORD) 2685 { 2686 DPRINT("Bad data type for InitiatorTargetId\n"); 2687 continue; 2688 } 2689 2690 ConfigInfo->InitiatorBusId[0] = *((PUCHAR) 2691 (Buffer + KeyValueInformation->DataOffset)); 2692 2693 /* Check / reset if needed */ 2694 if (ConfigInfo->InitiatorBusId[0] > ConfigInfo->MaximumNumberOfTargets - 1) 2695 ConfigInfo->InitiatorBusId[0] = (CCHAR)-1; 2696 2697 DPRINT("InitiatorTargetId = %d\n", ConfigInfo->InitiatorBusId[0]); 2698 } 2699 2700 /* Get ScsiDebug */ 2701 if (_wcsnicmp(KeyValueInformation->Name, L"ScsiDebug", 2702 KeyValueInformation->NameLength/2) == 0) 2703 { 2704 DPRINT("ScsiDebug key not supported\n"); 2705 } 2706 2707 /* Check for a breakpoint */ 2708 if (_wcsnicmp(KeyValueInformation->Name, L"BreakPointOnEntry", 2709 KeyValueInformation->NameLength/2) == 0) 2710 { 2711 DPRINT1("Breakpoint on entry requested!\n"); 2712 DbgBreakPoint(); 2713 } 2714 2715 /* Get DisableSynchronousTransfers */ 2716 if (_wcsnicmp(KeyValueInformation->Name, L"DisableSynchronousTransfers", 2717 KeyValueInformation->NameLength/2) == 0) 2718 { 2719 DeviceExtension->SrbFlags |= SRB_FLAGS_DISABLE_SYNCH_TRANSFER; 2720 DPRINT("Synch transfers disabled\n"); 2721 } 2722 2723 /* Get DisableDisconnects */ 2724 if (_wcsnicmp(KeyValueInformation->Name, L"DisableDisconnects", 2725 KeyValueInformation->NameLength/2) == 0) 2726 { 2727 DeviceExtension->SrbFlags |= SRB_FLAGS_DISABLE_DISCONNECT; 2728 DPRINT("Disconnects disabled\n"); 2729 } 2730 2731 /* Get DisableTaggedQueuing */ 2732 if (_wcsnicmp(KeyValueInformation->Name, L"DisableTaggedQueuing", 2733 KeyValueInformation->NameLength/2) == 0) 2734 { 2735 InternalConfigInfo->DisableTaggedQueueing = TRUE; 2736 DPRINT("Tagged queueing disabled\n"); 2737 } 2738 2739 /* Get DisableMultipleRequests */ 2740 if (_wcsnicmp(KeyValueInformation->Name, L"DisableMultipleRequests", 2741 KeyValueInformation->NameLength/2) == 0) 2742 { 2743 InternalConfigInfo->DisableMultipleLun = TRUE; 2744 DPRINT("Multiple requests disabled\n"); 2745 } 2746 2747 /* Get DriverParameters */ 2748 if (_wcsnicmp(KeyValueInformation->Name, L"DriverParameters", 2749 KeyValueInformation->NameLength/2) == 0) 2750 { 2751 /* Skip if nothing */ 2752 if (KeyValueInformation->DataLength == 0) 2753 continue; 2754 2755 /* If there was something previously allocated - free it */ 2756 if (InternalConfigInfo->Parameter != NULL) 2757 ExFreePool(InternalConfigInfo->Parameter); 2758 2759 /* Allocate it */ 2760 InternalConfigInfo->Parameter = ExAllocatePoolWithTag(NonPagedPool, 2761 KeyValueInformation->DataLength, TAG_SCSIPORT); 2762 2763 if (InternalConfigInfo->Parameter != NULL) 2764 { 2765 if (KeyValueInformation->Type != REG_SZ) 2766 { 2767 /* Just copy */ 2768 RtlCopyMemory( 2769 InternalConfigInfo->Parameter, 2770 (PCCHAR)KeyValueInformation + KeyValueInformation->DataOffset, 2771 KeyValueInformation->DataLength); 2772 } 2773 else 2774 { 2775 /* If it's a unicode string, convert it to ansi */ 2776 UnicodeString.Length = (USHORT)KeyValueInformation->DataLength; 2777 UnicodeString.MaximumLength = (USHORT)KeyValueInformation->DataLength; 2778 UnicodeString.Buffer = 2779 (PWSTR)((PCCHAR)KeyValueInformation + KeyValueInformation->DataOffset); 2780 2781 AnsiString.Length = 0; 2782 AnsiString.MaximumLength = (USHORT)KeyValueInformation->DataLength; 2783 AnsiString.Buffer = (PCHAR)InternalConfigInfo->Parameter; 2784 2785 Status = RtlUnicodeStringToAnsiString(&AnsiString, 2786 &UnicodeString, 2787 FALSE); 2788 2789 /* In case of error, free the allocated space */ 2790 if (!NT_SUCCESS(Status)) 2791 { 2792 ExFreePool(InternalConfigInfo->Parameter); 2793 InternalConfigInfo->Parameter = NULL; 2794 } 2795 2796 } 2797 } 2798 2799 DPRINT("Found driver parameter\n"); 2800 } 2801 2802 /* Get MaximumSGList */ 2803 if (_wcsnicmp(KeyValueInformation->Name, L"MaximumSGList", 2804 KeyValueInformation->NameLength/2) == 0) 2805 { 2806 if (KeyValueInformation->Type != REG_DWORD) 2807 { 2808 DPRINT("Bad data type for MaximumSGList\n"); 2809 continue; 2810 } 2811 2812 ConfigInfo->NumberOfPhysicalBreaks = *((PUCHAR)(Buffer + KeyValueInformation->DataOffset)); 2813 2814 /* Check / fix */ 2815 if (ConfigInfo->NumberOfPhysicalBreaks > SCSI_MAXIMUM_PHYSICAL_BREAKS) 2816 { 2817 ConfigInfo->NumberOfPhysicalBreaks = SCSI_MAXIMUM_PHYSICAL_BREAKS; 2818 } 2819 else if (ConfigInfo->NumberOfPhysicalBreaks < SCSI_MINIMUM_PHYSICAL_BREAKS) 2820 { 2821 ConfigInfo->NumberOfPhysicalBreaks = SCSI_MINIMUM_PHYSICAL_BREAKS; 2822 } 2823 2824 DPRINT("MaximumSGList = %d\n", ConfigInfo->NumberOfPhysicalBreaks); 2825 } 2826 2827 /* Get NumberOfRequests */ 2828 if (_wcsnicmp(KeyValueInformation->Name, L"NumberOfRequests", 2829 KeyValueInformation->NameLength/2) == 0) 2830 { 2831 if (KeyValueInformation->Type != REG_DWORD) 2832 { 2833 DPRINT("NumberOfRequests has wrong data type\n"); 2834 continue; 2835 } 2836 2837 DeviceExtension->RequestsNumber = *((PUCHAR)(Buffer + KeyValueInformation->DataOffset)); 2838 2839 /* Check / fix */ 2840 if (DeviceExtension->RequestsNumber < 16) 2841 { 2842 DeviceExtension->RequestsNumber = 16; 2843 } 2844 else if (DeviceExtension->RequestsNumber > 512) 2845 { 2846 DeviceExtension->RequestsNumber = 512; 2847 } 2848 2849 DPRINT("Number Of Requests = %d\n", DeviceExtension->RequestsNumber); 2850 } 2851 2852 /* Get resource list */ 2853 if (_wcsnicmp(KeyValueInformation->Name, L"ResourceList", 2854 KeyValueInformation->NameLength/2) == 0 || 2855 _wcsnicmp(KeyValueInformation->Name, L"Configuration Data", 2856 KeyValueInformation->NameLength/2) == 0 ) 2857 { 2858 if (KeyValueInformation->Type != REG_FULL_RESOURCE_DESCRIPTOR || 2859 KeyValueInformation->DataLength < sizeof(REG_FULL_RESOURCE_DESCRIPTOR)) 2860 { 2861 DPRINT("Bad data type for ResourceList\n"); 2862 continue; 2863 } 2864 else 2865 { 2866 DPRINT("Found ResourceList\n"); 2867 } 2868 2869 FullResource = (PCM_FULL_RESOURCE_DESCRIPTOR)(Buffer + KeyValueInformation->DataOffset); 2870 2871 /* Copy some info from it */ 2872 InternalConfigInfo->BusNumber = FullResource->BusNumber; 2873 ConfigInfo->SystemIoBusNumber = FullResource->BusNumber; 2874 2875 /* Loop through it */ 2876 for (Count = 0; Count < FullResource->PartialResourceList.Count; Count++) 2877 { 2878 /* Get partial descriptor */ 2879 PartialDescriptor = 2880 &FullResource->PartialResourceList.PartialDescriptors[Count]; 2881 2882 /* Check datalength */ 2883 if ((ULONG)((PCHAR)(PartialDescriptor + 1) - 2884 (PCHAR)FullResource) > KeyValueInformation->DataLength) 2885 { 2886 DPRINT("Resource data is of incorrect size\n"); 2887 break; 2888 } 2889 2890 switch (PartialDescriptor->Type) 2891 { 2892 case CmResourceTypePort: 2893 if (RangeCount >= ConfigInfo->NumberOfAccessRanges) 2894 { 2895 DPRINT("Too many access ranges\n"); 2896 continue; 2897 } 2898 2899 InternalConfigInfo->AccessRanges[RangeCount].RangeInMemory = FALSE; 2900 InternalConfigInfo->AccessRanges[RangeCount].RangeStart = PartialDescriptor->u.Port.Start; 2901 InternalConfigInfo->AccessRanges[RangeCount].RangeLength = PartialDescriptor->u.Port.Length; 2902 RangeCount++; 2903 2904 break; 2905 2906 case CmResourceTypeMemory: 2907 if (RangeCount >= ConfigInfo->NumberOfAccessRanges) 2908 { 2909 DPRINT("Too many access ranges\n"); 2910 continue; 2911 } 2912 2913 InternalConfigInfo->AccessRanges[RangeCount].RangeInMemory = TRUE; 2914 InternalConfigInfo->AccessRanges[RangeCount].RangeStart = PartialDescriptor->u.Memory.Start; 2915 InternalConfigInfo->AccessRanges[RangeCount].RangeLength = PartialDescriptor->u.Memory.Length; 2916 RangeCount++; 2917 2918 break; 2919 2920 case CmResourceTypeInterrupt: 2921 2922 if (Interrupt == 0) 2923 { 2924 ConfigInfo->BusInterruptLevel = 2925 PartialDescriptor->u.Interrupt.Level; 2926 2927 ConfigInfo->BusInterruptVector = 2928 PartialDescriptor->u.Interrupt.Vector; 2929 2930 ConfigInfo->InterruptMode = (PartialDescriptor->Flags & CM_RESOURCE_INTERRUPT_LATCHED) ? Latched : LevelSensitive; 2931 } 2932 else if (Interrupt == 1) 2933 { 2934 ConfigInfo->BusInterruptLevel2 = 2935 PartialDescriptor->u.Interrupt.Level; 2936 2937 ConfigInfo->BusInterruptVector2 = 2938 PartialDescriptor->u.Interrupt.Vector; 2939 2940 ConfigInfo->InterruptMode2 = (PartialDescriptor->Flags & CM_RESOURCE_INTERRUPT_LATCHED) ? Latched : LevelSensitive; 2941 } 2942 2943 Interrupt++; 2944 break; 2945 2946 case CmResourceTypeDma: 2947 2948 if (Dma == 0) 2949 { 2950 ConfigInfo->DmaChannel = PartialDescriptor->u.Dma.Channel; 2951 ConfigInfo->DmaPort = PartialDescriptor->u.Dma.Port; 2952 2953 if (PartialDescriptor->Flags & CM_RESOURCE_DMA_8) 2954 ConfigInfo->DmaWidth = Width8Bits; 2955 else if ((PartialDescriptor->Flags & CM_RESOURCE_DMA_16) || 2956 (PartialDescriptor->Flags & CM_RESOURCE_DMA_8_AND_16)) //??? 2957 ConfigInfo->DmaWidth = Width16Bits; 2958 else if (PartialDescriptor->Flags & CM_RESOURCE_DMA_32) 2959 ConfigInfo->DmaWidth = Width32Bits; 2960 } 2961 else if (Dma == 1) 2962 { 2963 ConfigInfo->DmaChannel2 = PartialDescriptor->u.Dma.Channel; 2964 ConfigInfo->DmaPort2 = PartialDescriptor->u.Dma.Port; 2965 2966 if (PartialDescriptor->Flags & CM_RESOURCE_DMA_8) 2967 ConfigInfo->DmaWidth2 = Width8Bits; 2968 else if ((PartialDescriptor->Flags & CM_RESOURCE_DMA_16) || 2969 (PartialDescriptor->Flags & CM_RESOURCE_DMA_8_AND_16)) //??? 2970 ConfigInfo->DmaWidth2 = Width16Bits; 2971 else if (PartialDescriptor->Flags & CM_RESOURCE_DMA_32) 2972 ConfigInfo->DmaWidth2 = Width32Bits; 2973 } 2974 2975 Dma++; 2976 break; 2977 2978 case CmResourceTypeDeviceSpecific: 2979 if (PartialDescriptor->u.DeviceSpecificData.DataSize < 2980 sizeof(CM_SCSI_DEVICE_DATA) || 2981 (PCHAR) (PartialDescriptor + 1) - (PCHAR)FullResource + 2982 PartialDescriptor->u.DeviceSpecificData.DataSize > 2983 KeyValueInformation->DataLength) 2984 { 2985 DPRINT("Resource data length is incorrect"); 2986 break; 2987 } 2988 2989 /* Set only one field from it */ 2990 ScsiDeviceData = (PCM_SCSI_DEVICE_DATA) (PartialDescriptor+1); 2991 ConfigInfo->InitiatorBusId[0] = ScsiDeviceData->HostIdentifier; 2992 break; 2993 } 2994 } 2995 } 2996 } 2997 } 2998 2999 NTSTATUS 3000 NTAPI 3001 SpQueryDeviceCallout(IN PVOID Context, 3002 IN PUNICODE_STRING PathName, 3003 IN INTERFACE_TYPE BusType, 3004 IN ULONG BusNumber, 3005 IN PKEY_VALUE_FULL_INFORMATION *BusInformation, 3006 IN CONFIGURATION_TYPE ControllerType, 3007 IN ULONG ControllerNumber, 3008 IN PKEY_VALUE_FULL_INFORMATION *ControllerInformation, 3009 IN CONFIGURATION_TYPE PeripheralType, 3010 IN ULONG PeripheralNumber, 3011 IN PKEY_VALUE_FULL_INFORMATION *PeripheralInformation) 3012 { 3013 PBOOLEAN Found = (PBOOLEAN)Context; 3014 /* We just set our Found variable to TRUE */ 3015 3016 *Found = TRUE; 3017 return STATUS_SUCCESS; 3018 } 3019 3020 IO_ALLOCATION_ACTION 3021 NTAPI 3022 ScsiPortAllocateAdapterChannel(IN PDEVICE_OBJECT DeviceObject, 3023 IN PIRP Irp, 3024 IN PVOID MapRegisterBase, 3025 IN PVOID Context) 3026 { 3027 KIRQL Irql; 3028 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension; 3029 3030 /* Guard access with the spinlock */ 3031 KeAcquireSpinLock(&DeviceExtension->SpinLock, &Irql); 3032 3033 /* Save MapRegisterBase we've got here */ 3034 DeviceExtension->MapRegisterBase = MapRegisterBase; 3035 3036 /* Start pending request */ 3037 KeSynchronizeExecution(DeviceExtension->Interrupt[0], 3038 ScsiPortStartPacket, DeviceObject); 3039 3040 /* Release spinlock we took */ 3041 KeReleaseSpinLock(&DeviceExtension->SpinLock, Irql); 3042 3043 return KeepObject; 3044 } 3045 3046 #undef ScsiPortConvertPhysicalAddressToUlong 3047 /* 3048 * @implemented 3049 */ 3050 ULONG NTAPI 3051 ScsiPortConvertPhysicalAddressToUlong(IN SCSI_PHYSICAL_ADDRESS Address) 3052 { 3053 DPRINT("ScsiPortConvertPhysicalAddressToUlong()\n"); 3054 return(Address.u.LowPart); 3055 } 3056