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 /* Set the buffering strategy here... */ 985 PortDeviceObject->Flags |= DO_DIRECT_IO; 986 PortDeviceObject->AlignmentRequirement = FILE_WORD_ALIGNMENT; /* FIXME: Is this really needed? */ 987 988 /* Fill Device Extension */ 989 DeviceExtension = PortDeviceObject->DeviceExtension; 990 RtlZeroMemory(DeviceExtension, DeviceExtensionSize); 991 DeviceExtension->Common.DeviceObject = PortDeviceObject; 992 DeviceExtension->Common.IsFDO = TRUE; 993 DeviceExtension->Length = DeviceExtensionSize; 994 DeviceExtension->PortNumber = SystemConfig->ScsiPortCount; 995 DeviceExtension->DeviceName = DeviceName; 996 997 /* Driver's routines... */ 998 DeviceExtension->HwInitialize = HwInitializationData->HwInitialize; 999 DeviceExtension->HwStartIo = HwInitializationData->HwStartIo; 1000 DeviceExtension->HwInterrupt = HwInitializationData->HwInterrupt; 1001 DeviceExtension->HwResetBus = HwInitializationData->HwResetBus; 1002 DeviceExtension->HwDmaStarted = HwInitializationData->HwDmaStarted; 1003 1004 /* Extensions sizes */ 1005 DeviceExtension->MiniPortExtensionSize = HwInitializationData->DeviceExtensionSize; 1006 DeviceExtension->LunExtensionSize = 1007 ALIGN_UP(HwInitializationData->SpecificLuExtensionSize, INT64); 1008 DeviceExtension->SrbExtensionSize = 1009 ALIGN_UP(HwInitializationData->SrbExtensionSize, INT64); 1010 1011 /* Fill some numbers (bus count, lun count, etc) */ 1012 DeviceExtension->MaxLunCount = SCSI_MAXIMUM_LOGICAL_UNITS; 1013 DeviceExtension->RequestsNumber = 16; 1014 1015 /* Initialize the spin lock in the controller extension */ 1016 KeInitializeSpinLock(&DeviceExtension->IrqLock); 1017 KeInitializeSpinLock(&DeviceExtension->SpinLock); 1018 1019 /* Initialize the DPC object */ 1020 IoInitializeDpcRequest(PortDeviceObject, 1021 ScsiPortDpcForIsr); 1022 1023 /* Initialize the device timer */ 1024 DeviceExtension->TimerCount = -1; 1025 IoInitializeTimer(PortDeviceObject, 1026 ScsiPortIoTimer, 1027 DeviceExtension); 1028 1029 /* Initialize miniport timer */ 1030 KeInitializeTimer(&DeviceExtension->MiniportTimer); 1031 KeInitializeDpc(&DeviceExtension->MiniportTimerDpc, 1032 SpiMiniportTimerDpc, 1033 PortDeviceObject); 1034 1035 CreatePortConfig: 1036 1037 /* Allocate and initialize port configuration info */ 1038 PortConfigSize = sizeof(PORT_CONFIGURATION_INFORMATION) + 1039 HwInitializationData->NumberOfAccessRanges * sizeof(ACCESS_RANGE); 1040 PortConfigSize = ALIGN_UP(PortConfigSize, INT64); 1041 DeviceExtension->PortConfig = ExAllocatePoolWithTag(NonPagedPool, PortConfigSize, TAG_SCSIPORT); 1042 1043 /* Fail if failed */ 1044 if (DeviceExtension->PortConfig == NULL) 1045 { 1046 Status = STATUS_INSUFFICIENT_RESOURCES; 1047 break; 1048 } 1049 1050 Status = SpiCreatePortConfig(DeviceExtension, 1051 HwInitializationData, 1052 &ConfigInfo, 1053 DeviceExtension->PortConfig, 1054 FirstConfigCall); 1055 1056 if (!NT_SUCCESS(Status)) 1057 { 1058 DPRINT("SpiCreatePortConfig() failed with Status 0x%08X\n", Status); 1059 break; 1060 } 1061 1062 PortConfig = DeviceExtension->PortConfig; 1063 1064 /* Copy extension sizes into the PortConfig */ 1065 PortConfig->SpecificLuExtensionSize = DeviceExtension->LunExtensionSize; 1066 PortConfig->SrbExtensionSize = DeviceExtension->SrbExtensionSize; 1067 1068 /* Initialize Access ranges */ 1069 if (HwInitializationData->NumberOfAccessRanges != 0) 1070 { 1071 PortConfig->AccessRanges = ALIGN_UP_POINTER(PortConfig + 1, INT64); 1072 1073 /* Copy the data */ 1074 RtlCopyMemory(PortConfig->AccessRanges, 1075 ConfigInfo.AccessRanges, 1076 HwInitializationData->NumberOfAccessRanges * sizeof(ACCESS_RANGE)); 1077 } 1078 1079 /* Search for matching PCI device */ 1080 if ((HwInitializationData->AdapterInterfaceType == PCIBus) && 1081 (HwInitializationData->VendorIdLength > 0) && 1082 (HwInitializationData->VendorId != NULL) && 1083 (HwInitializationData->DeviceIdLength > 0) && (HwInitializationData->DeviceId != NULL)) 1084 { 1085 PortConfig->BusInterruptLevel = 0; 1086 1087 /* Get PCI device data */ 1088 DPRINT( 1089 "VendorId '%.*s' DeviceId '%.*s'\n", HwInitializationData->VendorIdLength, 1090 HwInitializationData->VendorId, HwInitializationData->DeviceIdLength, 1091 HwInitializationData->DeviceId); 1092 1093 if (!SpiGetPciConfigData( 1094 DriverObject, PortDeviceObject, HwInitializationData, PortConfig, RegistryPath, 1095 ConfigInfo.BusNumber, &SlotNumber)) 1096 { 1097 /* Continue to the next bus, nothing here */ 1098 ConfigInfo.BusNumber++; 1099 DeviceExtension->PortConfig = NULL; 1100 ExFreePool(PortConfig); 1101 Again = FALSE; 1102 goto CreatePortConfig; 1103 } 1104 1105 if (!PortConfig->BusInterruptLevel) 1106 { 1107 /* Bypass this slot, because no interrupt was assigned */ 1108 DeviceExtension->PortConfig = NULL; 1109 ExFreePool(PortConfig); 1110 goto CreatePortConfig; 1111 } 1112 } 1113 else 1114 { 1115 DPRINT("Non-pci bus\n"); 1116 } 1117 1118 /* Note: HwFindAdapter is called once for each bus */ 1119 Again = FALSE; 1120 DPRINT("Calling HwFindAdapter() for Bus %lu\n", PortConfig->SystemIoBusNumber); 1121 Result = (HwInitializationData->HwFindAdapter)( 1122 &DeviceExtension->MiniPortDeviceExtension, HwContext, 0, /* BusInformation */ 1123 ConfigInfo.Parameter, /* ArgumentString */ 1124 PortConfig, &Again); 1125 1126 DPRINT("HwFindAdapter() Result: %lu Again: %s\n", Result, (Again) ? "True" : "False"); 1127 1128 /* Free MapRegisterBase, it's not needed anymore */ 1129 if (DeviceExtension->MapRegisterBase != NULL) 1130 { 1131 ExFreePool(DeviceExtension->MapRegisterBase); 1132 DeviceExtension->MapRegisterBase = NULL; 1133 } 1134 1135 /* If result is nothing good... */ 1136 if (Result != SP_RETURN_FOUND) 1137 { 1138 DPRINT("HwFindAdapter() Result: %lu\n", Result); 1139 1140 if (Result == SP_RETURN_NOT_FOUND) 1141 { 1142 /* We can continue on the next bus */ 1143 ConfigInfo.BusNumber++; 1144 Again = FALSE; 1145 1146 DeviceExtension->PortConfig = NULL; 1147 ExFreePool(PortConfig); 1148 goto CreatePortConfig; 1149 } 1150 1151 /* Otherwise, break */ 1152 Status = STATUS_INTERNAL_ERROR; 1153 break; 1154 } 1155 1156 DPRINT( 1157 "ScsiPortInitialize(): Found HBA! (%x), adapter Id %d\n", 1158 PortConfig->BusInterruptVector, PortConfig->InitiatorBusId[0]); 1159 1160 /* If the SRB extension size was updated */ 1161 if (!DeviceExtension->NonCachedExtension && 1162 (PortConfig->SrbExtensionSize != DeviceExtension->SrbExtensionSize)) 1163 { 1164 /* Set it (rounding to LONGLONG again) */ 1165 DeviceExtension->SrbExtensionSize = ALIGN_UP(PortConfig->SrbExtensionSize, INT64); 1166 } 1167 1168 /* The same with LUN extension size */ 1169 if (PortConfig->SpecificLuExtensionSize != DeviceExtension->LunExtensionSize) 1170 DeviceExtension->LunExtensionSize = PortConfig->SpecificLuExtensionSize; 1171 1172 /* Construct a resource list */ 1173 ResourceList = SpiConfigToResource(DeviceExtension, PortConfig); 1174 1175 PDEVICE_OBJECT LowerPDO = NULL; 1176 1177 Status = IoReportDetectedDevice(DriverObject, 1178 HwInitializationData->AdapterInterfaceType, 1179 ConfigInfo.BusNumber, 1180 PortConfig->SlotNumber, 1181 ResourceList, 1182 NULL, 1183 TRUE, 1184 &LowerPDO); 1185 1186 if (!NT_SUCCESS(Status)) 1187 { 1188 DPRINT1("IoReportDetectedDevice failed. Status: 0x%x\n", Status); 1189 __debugbreak(); 1190 break; 1191 } 1192 1193 DeviceExtension->Common.LowerDevice = IoAttachDeviceToDeviceStack(PortDeviceObject, LowerPDO); 1194 1195 ASSERT(DeviceExtension->Common.LowerDevice); 1196 1197 PortDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; 1198 1199 if (ResourceList) 1200 { 1201 ExFreePoolWithTag(ResourceList, TAG_SCSIPORT); 1202 } 1203 1204 /* Copy all stuff which we ever need from PortConfig to the DeviceExtension */ 1205 if (PortConfig->MaximumNumberOfTargets > SCSI_MAXIMUM_TARGETS_PER_BUS) 1206 DeviceExtension->MaxTargedIds = SCSI_MAXIMUM_TARGETS_PER_BUS; 1207 else 1208 DeviceExtension->MaxTargedIds = PortConfig->MaximumNumberOfTargets; 1209 1210 DeviceExtension->NumberOfBuses = PortConfig->NumberOfBuses; 1211 DeviceExtension->CachesData = PortConfig->CachesData; 1212 DeviceExtension->ReceiveEvent = PortConfig->ReceiveEvent; 1213 DeviceExtension->SupportsTaggedQueuing = PortConfig->TaggedQueuing; 1214 DeviceExtension->MultipleReqsPerLun = PortConfig->MultipleRequestPerLu; 1215 1216 /* Initialize bus scanning information */ 1217 size_t BusConfigSize = DeviceExtension->NumberOfBuses * sizeof(*DeviceExtension->Buses); 1218 DeviceExtension->Buses = ExAllocatePoolZero(NonPagedPool, BusConfigSize, TAG_SCSIPORT); 1219 if (!DeviceExtension->Buses) 1220 { 1221 DPRINT1("Out of resources!\n"); 1222 Status = STATUS_INSUFFICIENT_RESOURCES; 1223 break; 1224 } 1225 1226 // initialize bus data 1227 for (UINT8 pathId = 0; pathId < DeviceExtension->NumberOfBuses; pathId++) 1228 { 1229 DeviceExtension->Buses[pathId].BusIdentifier = 1230 DeviceExtension->PortConfig->InitiatorBusId[pathId]; 1231 InitializeListHead(&DeviceExtension->Buses[pathId].LunsListHead); 1232 } 1233 1234 /* If something was disabled via registry - apply it */ 1235 if (ConfigInfo.DisableMultipleLun) 1236 DeviceExtension->MultipleReqsPerLun = PortConfig->MultipleRequestPerLu = FALSE; 1237 1238 if (ConfigInfo.DisableTaggedQueueing) 1239 DeviceExtension->SupportsTaggedQueuing = PortConfig->MultipleRequestPerLu = FALSE; 1240 1241 /* Check if we need to alloc SRB data */ 1242 if (DeviceExtension->SupportsTaggedQueuing || DeviceExtension->MultipleReqsPerLun) 1243 { 1244 DeviceExtension->NeedSrbDataAlloc = TRUE; 1245 } 1246 else 1247 { 1248 DeviceExtension->NeedSrbDataAlloc = FALSE; 1249 } 1250 1251 /* Get a pointer to the port capabilities */ 1252 PortCapabilities = &DeviceExtension->PortCapabilities; 1253 1254 /* Copy one field there */ 1255 DeviceExtension->MapBuffers = PortConfig->MapBuffers; 1256 PortCapabilities->AdapterUsesPio = PortConfig->MapBuffers; 1257 1258 if (DeviceExtension->AdapterObject == NULL && 1259 (PortConfig->DmaChannel != SP_UNINITIALIZED_VALUE || PortConfig->Master)) 1260 { 1261 DPRINT1("DMA is not supported yet\n"); 1262 ASSERT(FALSE); 1263 } 1264 1265 if (DeviceExtension->SrbExtensionBuffer == NULL && 1266 (DeviceExtension->SrbExtensionSize != 0 || PortConfig->AutoRequestSense)) 1267 { 1268 DeviceExtension->SupportsAutoSense = PortConfig->AutoRequestSense; 1269 DeviceExtension->NeedSrbExtensionAlloc = TRUE; 1270 1271 /* Allocate common buffer */ 1272 Status = SpiAllocateCommonBuffer(DeviceExtension, 0); 1273 1274 /* Check for failure */ 1275 if (!NT_SUCCESS(Status)) 1276 break; 1277 } 1278 1279 /* Allocate SrbData, if needed */ 1280 if (DeviceExtension->NeedSrbDataAlloc) 1281 { 1282 ULONG Count; 1283 PSCSI_REQUEST_BLOCK_INFO SrbData; 1284 1285 if (DeviceExtension->SrbDataCount != 0) 1286 Count = DeviceExtension->SrbDataCount; 1287 else 1288 Count = DeviceExtension->RequestsNumber * 2; 1289 1290 /* Allocate the data */ 1291 SrbData = ExAllocatePoolWithTag( 1292 NonPagedPool, Count * sizeof(SCSI_REQUEST_BLOCK_INFO), TAG_SCSIPORT); 1293 if (SrbData == NULL) 1294 return STATUS_INSUFFICIENT_RESOURCES; 1295 1296 RtlZeroMemory(SrbData, Count * sizeof(SCSI_REQUEST_BLOCK_INFO)); 1297 1298 DeviceExtension->SrbInfo = SrbData; 1299 DeviceExtension->FreeSrbInfo = SrbData; 1300 DeviceExtension->SrbDataCount = Count; 1301 1302 /* Link it to the list */ 1303 while (Count > 0) 1304 { 1305 SrbData->Requests.Flink = (PLIST_ENTRY)(SrbData + 1); 1306 SrbData++; 1307 Count--; 1308 } 1309 1310 /* Mark the last entry of the list */ 1311 SrbData--; 1312 SrbData->Requests.Flink = NULL; 1313 } 1314 1315 /* Initialize port capabilities */ 1316 PortCapabilities = &DeviceExtension->PortCapabilities; 1317 PortCapabilities->Length = sizeof(IO_SCSI_CAPABILITIES); 1318 PortCapabilities->MaximumTransferLength = PortConfig->MaximumTransferLength; 1319 1320 if (PortConfig->ReceiveEvent) 1321 PortCapabilities->SupportedAsynchronousEvents |= SRBEV_SCSI_ASYNC_NOTIFICATION; 1322 1323 PortCapabilities->TaggedQueuing = DeviceExtension->SupportsTaggedQueuing; 1324 PortCapabilities->AdapterScansDown = PortConfig->AdapterScansDown; 1325 1326 if (PortConfig->AlignmentMask > PortDeviceObject->AlignmentRequirement) 1327 PortDeviceObject->AlignmentRequirement = PortConfig->AlignmentMask; 1328 1329 PortCapabilities->AlignmentMask = PortDeviceObject->AlignmentRequirement; 1330 1331 if (PortCapabilities->MaximumPhysicalPages == 0) 1332 { 1333 PortCapabilities->MaximumPhysicalPages = 1334 BYTES_TO_PAGES(PortCapabilities->MaximumTransferLength); 1335 1336 /* Apply miniport's limits */ 1337 if (PortConfig->NumberOfPhysicalBreaks < PortCapabilities->MaximumPhysicalPages) 1338 { 1339 PortCapabilities->MaximumPhysicalPages = PortConfig->NumberOfPhysicalBreaks; 1340 } 1341 } 1342 1343 FdoCallHWInitialize(DeviceExtension); 1344 1345 Status = FdoStartAdapter(DeviceExtension); 1346 1347 if (!NT_SUCCESS(Status)) 1348 { 1349 DPRINT1("Failed to start the legacy adapter. Status 0x%x\n", Status); 1350 break; 1351 } 1352 1353 FdoScanAdapter(DeviceExtension); 1354 1355 FirstConfigCall = FALSE; 1356 1357 /* Increase adapter number and bus number respectively */ 1358 ConfigInfo.AdapterNumber++; 1359 1360 if (!Again) 1361 ConfigInfo.BusNumber++; 1362 1363 DPRINT("Bus: %lu MaxBus: %lu\n", ConfigInfo.BusNumber, MaxBus); 1364 1365 DeviceFound = TRUE; 1366 } 1367 1368 /* Clean up the mess */ 1369 if (!NT_SUCCESS(Status) && PortDeviceObject) 1370 { 1371 FdoRemoveAdapter(DeviceExtension); 1372 } 1373 1374 /* Close registry keys */ 1375 if (ConfigInfo.ServiceKey != NULL) 1376 ZwClose(ConfigInfo.ServiceKey); 1377 1378 if (ConfigInfo.DeviceKey != NULL) 1379 ZwClose(ConfigInfo.DeviceKey); 1380 1381 if (ConfigInfo.BusKey != NULL) 1382 ZwClose(ConfigInfo.BusKey); 1383 1384 if (ConfigInfo.AccessRanges != NULL) 1385 ExFreePool(ConfigInfo.AccessRanges); 1386 1387 if (ConfigInfo.Parameter != NULL) 1388 ExFreePool(ConfigInfo.Parameter); 1389 1390 DPRINT("ScsiPortInitialize() done, Status = 0x%08X, DeviceFound = %d!\n", 1391 Status, DeviceFound); 1392 1393 return (DeviceFound == FALSE) ? Status : STATUS_SUCCESS; 1394 } 1395 1396 /* 1397 * @unimplemented 1398 */ 1399 VOID NTAPI 1400 ScsiPortIoMapTransfer(IN PVOID HwDeviceExtension, 1401 IN PSCSI_REQUEST_BLOCK Srb, 1402 IN PVOID LogicalAddress, 1403 IN ULONG Length) 1404 { 1405 DPRINT1("ScsiPortIoMapTransfer()\n"); 1406 UNIMPLEMENTED; 1407 } 1408 1409 /* 1410 * @unimplemented 1411 */ 1412 VOID NTAPI 1413 ScsiPortLogError(IN PVOID HwDeviceExtension, 1414 IN PSCSI_REQUEST_BLOCK Srb OPTIONAL, 1415 IN UCHAR PathId, 1416 IN UCHAR TargetId, 1417 IN UCHAR Lun, 1418 IN ULONG ErrorCode, 1419 IN ULONG UniqueId) 1420 { 1421 //PSCSI_PORT_DEVICE_EXTENSION DeviceExtension; 1422 1423 DPRINT1("ScsiPortLogError() called\n"); 1424 DPRINT1("PathId: 0x%02x TargetId: 0x%02x Lun: 0x%02x ErrorCode: 0x%08lx UniqueId: 0x%08lx\n", 1425 PathId, TargetId, Lun, ErrorCode, UniqueId); 1426 1427 //DeviceExtension = CONTAINING_RECORD(HwDeviceExtension, SCSI_PORT_DEVICE_EXTENSION, MiniPortDeviceExtension); 1428 1429 1430 DPRINT("ScsiPortLogError() done\n"); 1431 } 1432 1433 /* 1434 * @implemented 1435 */ 1436 VOID NTAPI 1437 ScsiPortMoveMemory(OUT PVOID Destination, 1438 IN PVOID Source, 1439 IN ULONG Length) 1440 { 1441 RtlMoveMemory(Destination, 1442 Source, 1443 Length); 1444 } 1445 1446 1447 /* 1448 * @implemented 1449 */ 1450 VOID 1451 ScsiPortNotification(IN SCSI_NOTIFICATION_TYPE NotificationType, IN PVOID HwDeviceExtension, ...) 1452 { 1453 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension; 1454 va_list ap; 1455 1456 DPRINT("ScsiPortNotification() called\n"); 1457 1458 DeviceExtension = 1459 CONTAINING_RECORD(HwDeviceExtension, SCSI_PORT_DEVICE_EXTENSION, MiniPortDeviceExtension); 1460 1461 DPRINT("DeviceExtension %p\n", DeviceExtension); 1462 1463 va_start(ap, HwDeviceExtension); 1464 1465 switch (NotificationType) 1466 { 1467 case RequestComplete: 1468 { 1469 PSCSI_REQUEST_BLOCK Srb; 1470 PSCSI_REQUEST_BLOCK_INFO SrbData; 1471 1472 Srb = (PSCSI_REQUEST_BLOCK)va_arg(ap, PSCSI_REQUEST_BLOCK); 1473 1474 DPRINT("Notify: RequestComplete (Srb %p)\n", Srb); 1475 1476 /* Make sure Srb is alright */ 1477 ASSERT(Srb->SrbStatus != SRB_STATUS_PENDING); 1478 ASSERT( 1479 Srb->Function != SRB_FUNCTION_EXECUTE_SCSI || 1480 Srb->SrbStatus != SRB_STATUS_SUCCESS || Srb->ScsiStatus == SCSISTAT_GOOD); 1481 1482 if (!(Srb->SrbFlags & SRB_FLAGS_IS_ACTIVE)) 1483 { 1484 /* It's been already completed */ 1485 va_end(ap); 1486 return; 1487 } 1488 1489 /* It's not active anymore */ 1490 Srb->SrbFlags &= ~SRB_FLAGS_IS_ACTIVE; 1491 1492 if (Srb->Function == SRB_FUNCTION_ABORT_COMMAND) 1493 { 1494 /* TODO: Treat it specially */ 1495 ASSERT(FALSE); 1496 } 1497 else 1498 { 1499 PIO_STACK_LOCATION IoStack = IoGetCurrentIrpStackLocation(Srb->OriginalRequest); 1500 PSCSI_PORT_LUN_EXTENSION LunExtension = IoStack->DeviceObject->DeviceExtension; 1501 ASSERT(LunExtension && !LunExtension->Common.IsFDO); 1502 1503 /* Get the SRB data */ 1504 SrbData = SpiGetSrbData(DeviceExtension, LunExtension, Srb->QueueTag); 1505 1506 /* Make sure there are no CompletedRequests and there is a Srb */ 1507 ASSERT(SrbData->CompletedRequests == NULL && SrbData->Srb != NULL); 1508 1509 /* If it's a read/write request, make sure it has data inside it */ 1510 if ((Srb->SrbStatus == SRB_STATUS_SUCCESS) && 1511 ((Srb->Cdb[0] == SCSIOP_READ) || (Srb->Cdb[0] == SCSIOP_WRITE))) 1512 { 1513 ASSERT(Srb->DataTransferLength); 1514 } 1515 1516 SrbData->CompletedRequests = DeviceExtension->InterruptData.CompletedRequests; 1517 DeviceExtension->InterruptData.CompletedRequests = SrbData; 1518 } 1519 } 1520 break; 1521 1522 case NextRequest: 1523 DPRINT("Notify: NextRequest\n"); 1524 DeviceExtension->InterruptData.Flags |= SCSI_PORT_NEXT_REQUEST_READY; 1525 break; 1526 1527 case NextLuRequest: 1528 { 1529 UCHAR PathId; 1530 UCHAR TargetId; 1531 UCHAR Lun; 1532 PSCSI_PORT_LUN_EXTENSION LunExtension; 1533 1534 PathId = (UCHAR)va_arg(ap, int); 1535 TargetId = (UCHAR)va_arg(ap, int); 1536 Lun = (UCHAR)va_arg(ap, int); 1537 1538 DPRINT( 1539 "Notify: NextLuRequest(PathId %u TargetId %u Lun %u)\n", PathId, TargetId, Lun); 1540 1541 /* Mark it in the flags field */ 1542 DeviceExtension->InterruptData.Flags |= SCSI_PORT_NEXT_REQUEST_READY; 1543 1544 /* Get the LUN extension */ 1545 LunExtension = GetLunByPath(DeviceExtension, PathId, TargetId, Lun); 1546 1547 /* If returned LunExtension is NULL, break out */ 1548 if (!LunExtension) 1549 break; 1550 1551 /* This request should not be processed if */ 1552 if ((LunExtension->ReadyLun) || (LunExtension->SrbInfo.Srb)) 1553 { 1554 /* Nothing to do here */ 1555 break; 1556 } 1557 1558 /* Add this LUN to the list */ 1559 LunExtension->ReadyLun = DeviceExtension->InterruptData.ReadyLun; 1560 DeviceExtension->InterruptData.ReadyLun = LunExtension; 1561 } 1562 break; 1563 1564 case ResetDetected: 1565 DPRINT("Notify: ResetDetected\n"); 1566 /* Add RESET flags */ 1567 DeviceExtension->InterruptData.Flags |= SCSI_PORT_RESET | SCSI_PORT_RESET_REPORTED; 1568 break; 1569 1570 case CallDisableInterrupts: 1571 DPRINT1("UNIMPLEMENTED SCSI Notification called: CallDisableInterrupts!\n"); 1572 break; 1573 1574 case CallEnableInterrupts: 1575 DPRINT1("UNIMPLEMENTED SCSI Notification called: CallEnableInterrupts!\n"); 1576 break; 1577 1578 case RequestTimerCall: 1579 DPRINT("Notify: RequestTimerCall\n"); 1580 DeviceExtension->InterruptData.Flags |= SCSI_PORT_TIMER_NEEDED; 1581 DeviceExtension->InterruptData.HwScsiTimer = (PHW_TIMER)va_arg(ap, PHW_TIMER); 1582 DeviceExtension->InterruptData.MiniportTimerValue = (ULONG)va_arg(ap, ULONG); 1583 break; 1584 1585 case BusChangeDetected: 1586 DPRINT1("UNIMPLEMENTED SCSI Notification called: BusChangeDetected!\n"); 1587 break; 1588 1589 default: 1590 DPRINT1("Unsupported notification from WMI: %lu\n", NotificationType); 1591 break; 1592 } 1593 1594 va_end(ap); 1595 1596 /* Request a DPC after we're done with the interrupt */ 1597 DeviceExtension->InterruptData.Flags |= SCSI_PORT_NOTIFICATION_NEEDED; 1598 } 1599 1600 /* 1601 * @implemented 1602 */ 1603 BOOLEAN NTAPI 1604 ScsiPortValidateRange(IN PVOID HwDeviceExtension, 1605 IN INTERFACE_TYPE BusType, 1606 IN ULONG SystemIoBusNumber, 1607 IN SCSI_PHYSICAL_ADDRESS IoAddress, 1608 IN ULONG NumberOfBytes, 1609 IN BOOLEAN InIoSpace) 1610 { 1611 DPRINT("ScsiPortValidateRange()\n"); 1612 return(TRUE); 1613 } 1614 1615 1616 /* INTERNAL FUNCTIONS ********************************************************/ 1617 1618 static VOID 1619 SpiResourceToConfig(IN PHW_INITIALIZATION_DATA HwInitializationData, 1620 IN PCM_FULL_RESOURCE_DESCRIPTOR ResourceDescriptor, 1621 IN PPORT_CONFIGURATION_INFORMATION PortConfig) 1622 { 1623 PACCESS_RANGE AccessRange; 1624 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialData; 1625 ULONG RangeNumber; 1626 ULONG Index; 1627 ULONG Interrupt = 0; 1628 ULONG Dma = 0; 1629 1630 RangeNumber = 0; 1631 1632 /* Loop through all entries */ 1633 for (Index = 0; Index < ResourceDescriptor->PartialResourceList.Count; Index++) 1634 { 1635 PartialData = &ResourceDescriptor->PartialResourceList.PartialDescriptors[Index]; 1636 1637 switch (PartialData->Type) 1638 { 1639 case CmResourceTypePort: 1640 /* Copy access ranges */ 1641 if (RangeNumber < HwInitializationData->NumberOfAccessRanges) 1642 { 1643 AccessRange = &((*(PortConfig->AccessRanges))[RangeNumber]); 1644 1645 AccessRange->RangeStart = PartialData->u.Port.Start; 1646 AccessRange->RangeLength = PartialData->u.Port.Length; 1647 1648 AccessRange->RangeInMemory = FALSE; 1649 RangeNumber++; 1650 } 1651 break; 1652 1653 case CmResourceTypeMemory: 1654 /* Copy access ranges */ 1655 if (RangeNumber < HwInitializationData->NumberOfAccessRanges) 1656 { 1657 AccessRange = &((*(PortConfig->AccessRanges))[RangeNumber]); 1658 1659 AccessRange->RangeStart = PartialData->u.Memory.Start; 1660 AccessRange->RangeLength = PartialData->u.Memory.Length; 1661 1662 AccessRange->RangeInMemory = TRUE; 1663 RangeNumber++; 1664 } 1665 break; 1666 1667 case CmResourceTypeInterrupt: 1668 1669 if (Interrupt == 0) 1670 { 1671 /* Copy interrupt data */ 1672 PortConfig->BusInterruptLevel = PartialData->u.Interrupt.Level; 1673 PortConfig->BusInterruptVector = PartialData->u.Interrupt.Vector; 1674 1675 /* Set interrupt mode accordingly to the resource */ 1676 if (PartialData->Flags == CM_RESOURCE_INTERRUPT_LATCHED) 1677 { 1678 PortConfig->InterruptMode = Latched; 1679 } 1680 else if (PartialData->Flags == CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE) 1681 { 1682 PortConfig->InterruptMode = LevelSensitive; 1683 } 1684 } 1685 else if (Interrupt == 1) 1686 { 1687 /* Copy interrupt data */ 1688 PortConfig->BusInterruptLevel2 = PartialData->u.Interrupt.Level; 1689 PortConfig->BusInterruptVector2 = PartialData->u.Interrupt.Vector; 1690 1691 /* Set interrupt mode accordingly to the resource */ 1692 if (PartialData->Flags == CM_RESOURCE_INTERRUPT_LATCHED) 1693 { 1694 PortConfig->InterruptMode2 = Latched; 1695 } 1696 else if (PartialData->Flags == CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE) 1697 { 1698 PortConfig->InterruptMode2 = LevelSensitive; 1699 } 1700 } 1701 1702 Interrupt++; 1703 break; 1704 1705 case CmResourceTypeDma: 1706 1707 if (Dma == 0) 1708 { 1709 PortConfig->DmaChannel = PartialData->u.Dma.Channel; 1710 PortConfig->DmaPort = PartialData->u.Dma.Port; 1711 1712 if (PartialData->Flags & CM_RESOURCE_DMA_8) 1713 PortConfig->DmaWidth = Width8Bits; 1714 else if ((PartialData->Flags & CM_RESOURCE_DMA_16) || 1715 (PartialData->Flags & CM_RESOURCE_DMA_8_AND_16)) //??? 1716 PortConfig->DmaWidth = Width16Bits; 1717 else if (PartialData->Flags & CM_RESOURCE_DMA_32) 1718 PortConfig->DmaWidth = Width32Bits; 1719 } 1720 else if (Dma == 1) 1721 { 1722 PortConfig->DmaChannel2 = PartialData->u.Dma.Channel; 1723 PortConfig->DmaPort2 = PartialData->u.Dma.Port; 1724 1725 if (PartialData->Flags & CM_RESOURCE_DMA_8) 1726 PortConfig->DmaWidth2 = Width8Bits; 1727 else if ((PartialData->Flags & CM_RESOURCE_DMA_16) || 1728 (PartialData->Flags & CM_RESOURCE_DMA_8_AND_16)) //??? 1729 PortConfig->DmaWidth2 = Width16Bits; 1730 else if (PartialData->Flags & CM_RESOURCE_DMA_32) 1731 PortConfig->DmaWidth2 = Width32Bits; 1732 } 1733 break; 1734 } 1735 } 1736 } 1737 1738 static PCM_RESOURCE_LIST 1739 SpiConfigToResource(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension, 1740 PPORT_CONFIGURATION_INFORMATION PortConfig) 1741 { 1742 PCONFIGURATION_INFORMATION ConfigInfo; 1743 PCM_RESOURCE_LIST ResourceList; 1744 PCM_PARTIAL_RESOURCE_DESCRIPTOR ResourceDescriptor; 1745 PACCESS_RANGE AccessRange; 1746 ULONG ListLength = 0, i, FullSize; 1747 ULONG Interrupt, Dma; 1748 1749 /* Get current Atdisk usage from the system */ 1750 ConfigInfo = IoGetConfigurationInformation(); 1751 1752 if (PortConfig->AtdiskPrimaryClaimed) 1753 ConfigInfo->AtDiskPrimaryAddressClaimed = TRUE; 1754 1755 if (PortConfig->AtdiskSecondaryClaimed) 1756 ConfigInfo->AtDiskSecondaryAddressClaimed = TRUE; 1757 1758 /* Do we use DMA? */ 1759 if (PortConfig->DmaChannel != SP_UNINITIALIZED_VALUE || 1760 PortConfig->DmaPort != SP_UNINITIALIZED_VALUE) 1761 { 1762 Dma = 1; 1763 1764 if (PortConfig->DmaChannel2 != SP_UNINITIALIZED_VALUE || 1765 PortConfig->DmaPort2 != SP_UNINITIALIZED_VALUE) 1766 Dma++; 1767 } 1768 else 1769 { 1770 Dma = 0; 1771 } 1772 ListLength += Dma; 1773 1774 /* How many interrupts to we have? */ 1775 Interrupt = DeviceExtension->InterruptCount; 1776 ListLength += Interrupt; 1777 1778 /* How many access ranges do we use? */ 1779 AccessRange = &((*(PortConfig->AccessRanges))[0]); 1780 for (i = 0; i < PortConfig->NumberOfAccessRanges; i++) 1781 { 1782 if (AccessRange->RangeLength != 0) 1783 ListLength++; 1784 1785 AccessRange++; 1786 } 1787 1788 /* Allocate the resource list, since we know its size now */ 1789 FullSize = sizeof(CM_RESOURCE_LIST) + (ListLength - 1) * 1790 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR); 1791 1792 ResourceList = (PCM_RESOURCE_LIST)ExAllocatePoolWithTag(PagedPool, FullSize, TAG_SCSIPORT); 1793 1794 if (!ResourceList) 1795 return NULL; 1796 1797 /* Zero it */ 1798 RtlZeroMemory(ResourceList, FullSize); 1799 1800 /* Initialize it */ 1801 ResourceList->Count = 1; 1802 ResourceList->List[0].InterfaceType = PortConfig->AdapterInterfaceType; 1803 ResourceList->List[0].BusNumber = PortConfig->SystemIoBusNumber; 1804 ResourceList->List[0].PartialResourceList.Count = ListLength; 1805 ResourceDescriptor = ResourceList->List[0].PartialResourceList.PartialDescriptors; 1806 1807 /* Copy access ranges array over */ 1808 for (i = 0; i < PortConfig->NumberOfAccessRanges; i++) 1809 { 1810 AccessRange = &((*(PortConfig->AccessRanges))[i]); 1811 1812 /* If the range is empty - skip it */ 1813 if (AccessRange->RangeLength == 0) 1814 continue; 1815 1816 if (AccessRange->RangeInMemory) 1817 { 1818 ResourceDescriptor->Type = CmResourceTypeMemory; 1819 ResourceDescriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE; 1820 } 1821 else 1822 { 1823 ResourceDescriptor->Type = CmResourceTypePort; 1824 ResourceDescriptor->Flags = CM_RESOURCE_PORT_IO; 1825 } 1826 1827 ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive; 1828 1829 ResourceDescriptor->u.Memory.Start = AccessRange->RangeStart; 1830 ResourceDescriptor->u.Memory.Length = AccessRange->RangeLength; 1831 1832 ResourceDescriptor++; 1833 } 1834 1835 /* If we use interrupt(s), copy them */ 1836 while (Interrupt) 1837 { 1838 ResourceDescriptor->Type = CmResourceTypeInterrupt; 1839 1840 if (PortConfig->AdapterInterfaceType == MicroChannel || 1841 ((Interrupt == 2) ? PortConfig->InterruptMode2 : PortConfig->InterruptMode) == LevelSensitive) 1842 { 1843 ResourceDescriptor->ShareDisposition = CmResourceShareShared; 1844 ResourceDescriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE; 1845 } 1846 else 1847 { 1848 ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive; 1849 ResourceDescriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED; 1850 } 1851 1852 ResourceDescriptor->u.Interrupt.Level = (Interrupt == 2) ? PortConfig->BusInterruptLevel2 : PortConfig->BusInterruptLevel; 1853 ResourceDescriptor->u.Interrupt.Vector = (Interrupt == 2) ? PortConfig->BusInterruptVector2 : PortConfig->BusInterruptVector; 1854 ResourceDescriptor->u.Interrupt.Affinity = 0; 1855 1856 ResourceDescriptor++; 1857 Interrupt--; 1858 } 1859 1860 /* Copy DMA data */ 1861 while (Dma) 1862 { 1863 ResourceDescriptor->Type = CmResourceTypeDma; 1864 ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive; 1865 ResourceDescriptor->u.Dma.Channel = (Dma == 2) ? PortConfig->DmaChannel2 : PortConfig->DmaChannel; 1866 ResourceDescriptor->u.Dma.Port = (Dma == 2) ? PortConfig->DmaPort2 : PortConfig->DmaPort; 1867 ResourceDescriptor->Flags = 0; 1868 1869 if (((Dma == 2) ? PortConfig->DmaWidth2 : PortConfig->DmaWidth) == Width8Bits) 1870 ResourceDescriptor->Flags |= CM_RESOURCE_DMA_8; 1871 else if (((Dma == 2) ? PortConfig->DmaWidth2 : PortConfig->DmaWidth) == Width16Bits) 1872 ResourceDescriptor->Flags |= CM_RESOURCE_DMA_16; 1873 else 1874 ResourceDescriptor->Flags |= CM_RESOURCE_DMA_32; 1875 1876 if (((Dma == 2) ? PortConfig->DmaChannel2 : PortConfig->DmaChannel) == SP_UNINITIALIZED_VALUE) 1877 ResourceDescriptor->u.Dma.Channel = 0; 1878 1879 if (((Dma == 2) ? PortConfig->DmaPort2 : PortConfig->DmaPort) == SP_UNINITIALIZED_VALUE) 1880 ResourceDescriptor->u.Dma.Port = 0; 1881 1882 ResourceDescriptor++; 1883 Dma--; 1884 } 1885 1886 return ResourceList; 1887 } 1888 1889 1890 static BOOLEAN 1891 SpiGetPciConfigData(IN PDRIVER_OBJECT DriverObject, 1892 IN PDEVICE_OBJECT DeviceObject, 1893 IN struct _HW_INITIALIZATION_DATA *HwInitializationData, 1894 IN OUT PPORT_CONFIGURATION_INFORMATION PortConfig, 1895 IN PUNICODE_STRING RegistryPath, 1896 IN ULONG BusNumber, 1897 IN OUT PPCI_SLOT_NUMBER NextSlotNumber) 1898 { 1899 PCI_COMMON_CONFIG PciConfig; 1900 PCI_SLOT_NUMBER SlotNumber; 1901 ULONG DataSize; 1902 ULONG DeviceNumber; 1903 ULONG FunctionNumber; 1904 CHAR VendorIdString[8]; 1905 CHAR DeviceIdString[8]; 1906 UNICODE_STRING UnicodeStr; 1907 PCM_RESOURCE_LIST ResourceList = NULL; 1908 NTSTATUS Status; 1909 1910 DPRINT ("SpiGetPciConfiguration() called\n"); 1911 1912 SlotNumber.u.AsULONG = 0; 1913 1914 /* Loop through all devices */ 1915 for (DeviceNumber = NextSlotNumber->u.bits.DeviceNumber; DeviceNumber < PCI_MAX_DEVICES; DeviceNumber++) 1916 { 1917 SlotNumber.u.bits.DeviceNumber = DeviceNumber; 1918 1919 /* Loop through all functions */ 1920 for (FunctionNumber = NextSlotNumber->u.bits.FunctionNumber; FunctionNumber < PCI_MAX_FUNCTION; FunctionNumber++) 1921 { 1922 SlotNumber.u.bits.FunctionNumber = FunctionNumber; 1923 1924 /* Get PCI config bytes */ 1925 DataSize = HalGetBusData(PCIConfiguration, 1926 BusNumber, 1927 SlotNumber.u.AsULONG, 1928 &PciConfig, 1929 sizeof(ULONG)); 1930 1931 /* If result of HalGetBusData is 0, then the bus is wrong */ 1932 if (DataSize == 0) 1933 return FALSE; 1934 1935 /* Check if result is PCI_INVALID_VENDORID or too small */ 1936 if ((DataSize < sizeof(ULONG)) || 1937 (PciConfig.VendorID == PCI_INVALID_VENDORID)) 1938 { 1939 /* Continue to try the next function */ 1940 continue; 1941 } 1942 1943 sprintf (VendorIdString, "%04hx", PciConfig.VendorID); 1944 sprintf (DeviceIdString, "%04hx", PciConfig.DeviceID); 1945 1946 if (_strnicmp(VendorIdString, HwInitializationData->VendorId, HwInitializationData->VendorIdLength) || 1947 _strnicmp(DeviceIdString, HwInitializationData->DeviceId, HwInitializationData->DeviceIdLength)) 1948 { 1949 /* It is not our device */ 1950 continue; 1951 } 1952 1953 DPRINT("Found device 0x%04hx 0x%04hx at %1lu %2lu %1lu\n", 1954 PciConfig.VendorID, 1955 PciConfig.DeviceID, 1956 BusNumber, 1957 SlotNumber.u.bits.DeviceNumber, 1958 SlotNumber.u.bits.FunctionNumber); 1959 1960 1961 RtlInitUnicodeString(&UnicodeStr, L"ScsiAdapter"); 1962 Status = HalAssignSlotResources(RegistryPath, 1963 &UnicodeStr, 1964 DriverObject, 1965 DeviceObject, 1966 PCIBus, 1967 BusNumber, 1968 SlotNumber.u.AsULONG, 1969 &ResourceList); 1970 1971 if (!NT_SUCCESS(Status)) 1972 break; 1973 1974 /* Create configuration information */ 1975 SpiResourceToConfig(HwInitializationData, 1976 ResourceList->List, 1977 PortConfig); 1978 1979 /* Free the resource list */ 1980 ExFreePool(ResourceList); 1981 1982 /* Set dev & fn numbers */ 1983 NextSlotNumber->u.bits.DeviceNumber = DeviceNumber; 1984 NextSlotNumber->u.bits.FunctionNumber = FunctionNumber + 1; 1985 1986 /* Save the slot number */ 1987 PortConfig->SlotNumber = SlotNumber.u.AsULONG; 1988 1989 return TRUE; 1990 } 1991 NextSlotNumber->u.bits.FunctionNumber = 0; 1992 } 1993 1994 NextSlotNumber->u.bits.DeviceNumber = 0; 1995 DPRINT ("No device found\n"); 1996 1997 return FALSE; 1998 } 1999 2000 2001 2002 /********************************************************************** 2003 * NAME INTERNAL 2004 * ScsiPortCreateClose 2005 * 2006 * DESCRIPTION 2007 * Answer requests for Create/Close calls: a null operation. 2008 * 2009 * RUN LEVEL 2010 * PASSIVE_LEVEL 2011 * 2012 * ARGUMENTS 2013 * DeviceObject 2014 * Pointer to a device object. 2015 * 2016 * Irp 2017 * Pointer to an IRP. 2018 * 2019 * RETURN VALUE 2020 * Status. 2021 */ 2022 2023 static NTSTATUS NTAPI 2024 ScsiPortCreateClose(IN PDEVICE_OBJECT DeviceObject, 2025 IN PIRP Irp) 2026 { 2027 DPRINT("ScsiPortCreateClose()\n"); 2028 2029 Irp->IoStatus.Status = STATUS_SUCCESS; 2030 IoCompleteRequest(Irp, IO_NO_INCREMENT); 2031 2032 return STATUS_SUCCESS; 2033 } 2034 2035 IO_ALLOCATION_ACTION 2036 NTAPI 2037 SpiAdapterControl(PDEVICE_OBJECT DeviceObject, 2038 PIRP Irp, 2039 PVOID MapRegisterBase, 2040 PVOID Context) 2041 { 2042 PSCSI_REQUEST_BLOCK Srb; 2043 PSCSI_SG_ADDRESS ScatterGatherList; 2044 KIRQL CurrentIrql; 2045 PIO_STACK_LOCATION IrpStack; 2046 ULONG TotalLength = 0; 2047 PSCSI_REQUEST_BLOCK_INFO SrbInfo; 2048 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension; 2049 PUCHAR DataVA; 2050 BOOLEAN WriteToDevice; 2051 2052 /* Get pointers to SrbInfo and DeviceExtension */ 2053 SrbInfo = (PSCSI_REQUEST_BLOCK_INFO)Context; 2054 DeviceExtension = DeviceObject->DeviceExtension; 2055 2056 /* Get pointer to SRB */ 2057 IrpStack = IoGetCurrentIrpStackLocation(Irp); 2058 Srb = (PSCSI_REQUEST_BLOCK)IrpStack->Parameters.Others.Argument1; 2059 2060 /* Depending on the map registers number, we allocate 2061 either from NonPagedPool, or from our static list */ 2062 if (SrbInfo->NumberOfMapRegisters > MAX_SG_LIST) 2063 { 2064 SrbInfo->ScatterGather = ExAllocatePoolWithTag( 2065 NonPagedPool, SrbInfo->NumberOfMapRegisters * sizeof(SCSI_SG_ADDRESS), TAG_SCSIPORT); 2066 2067 if (SrbInfo->ScatterGather == NULL) 2068 ASSERT(FALSE); 2069 2070 Srb->SrbFlags |= SRB_FLAGS_SGLIST_FROM_POOL; 2071 } 2072 else 2073 { 2074 SrbInfo->ScatterGather = SrbInfo->ScatterGatherList; 2075 } 2076 2077 /* Use chosen SG list source */ 2078 ScatterGatherList = SrbInfo->ScatterGather; 2079 2080 /* Save map registers base */ 2081 SrbInfo->BaseOfMapRegister = MapRegisterBase; 2082 2083 /* Determine WriteToDevice flag */ 2084 WriteToDevice = Srb->SrbFlags & SRB_FLAGS_DATA_OUT ? TRUE : FALSE; 2085 2086 /* Get virtual address of the data buffer */ 2087 DataVA = (PUCHAR)MmGetMdlVirtualAddress(Irp->MdlAddress) + 2088 ((PCHAR)Srb->DataBuffer - SrbInfo->DataOffset); 2089 2090 /* Build the actual SG list */ 2091 while (TotalLength < Srb->DataTransferLength) 2092 { 2093 if (!ScatterGatherList) 2094 break; 2095 2096 ScatterGatherList->Length = Srb->DataTransferLength - TotalLength; 2097 ScatterGatherList->PhysicalAddress = IoMapTransfer(DeviceExtension->AdapterObject, 2098 Irp->MdlAddress, 2099 MapRegisterBase, 2100 DataVA + TotalLength, 2101 &ScatterGatherList->Length, 2102 WriteToDevice); 2103 2104 TotalLength += ScatterGatherList->Length; 2105 ScatterGatherList++; 2106 } 2107 2108 /* Schedule an active request */ 2109 InterlockedIncrement(&DeviceExtension->ActiveRequestCounter ); 2110 KeAcquireSpinLock(&DeviceExtension->SpinLock, &CurrentIrql); 2111 KeSynchronizeExecution(DeviceExtension->Interrupt[0], 2112 ScsiPortStartPacket, 2113 DeviceObject); 2114 KeReleaseSpinLock(&DeviceExtension->SpinLock, CurrentIrql); 2115 2116 return DeallocateObjectKeepRegisters; 2117 } 2118 2119 BOOLEAN 2120 NTAPI 2121 ScsiPortIsr( 2122 _In_ PKINTERRUPT Interrupt, 2123 _In_ PVOID ServiceContext) 2124 { 2125 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension; 2126 2127 DPRINT("ScsiPortIsr() called!\n"); 2128 2129 DeviceExtension = (PSCSI_PORT_DEVICE_EXTENSION)ServiceContext; 2130 2131 /* If interrupts are disabled - we don't expect any */ 2132 if (DeviceExtension->InterruptData.Flags & SCSI_PORT_DISABLE_INTERRUPTS) 2133 return FALSE; 2134 2135 /* Call miniport's HwInterrupt routine */ 2136 if (DeviceExtension->HwInterrupt(&DeviceExtension->MiniPortDeviceExtension) == FALSE) 2137 { 2138 /* This interrupt doesn't belong to us */ 2139 return FALSE; 2140 } 2141 2142 /* If flag of notification is set - queue a DPC */ 2143 if (DeviceExtension->InterruptData.Flags & SCSI_PORT_NOTIFICATION_NEEDED) 2144 { 2145 IoRequestDpc(DeviceExtension->Common.DeviceObject, 2146 DeviceExtension->CurrentIrp, 2147 DeviceExtension); 2148 } 2149 2150 return TRUE; 2151 } 2152 2153 BOOLEAN 2154 NTAPI 2155 SpiProcessTimeout(PVOID ServiceContext) 2156 { 2157 PDEVICE_OBJECT DeviceObject = (PDEVICE_OBJECT)ServiceContext; 2158 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension; 2159 ULONG Bus; 2160 2161 DPRINT("SpiProcessTimeout() entered\n"); 2162 2163 DeviceExtension->TimerCount = -1; 2164 2165 if (DeviceExtension->InterruptData.Flags & SCSI_PORT_RESET) 2166 { 2167 DeviceExtension->InterruptData.Flags &= ~SCSI_PORT_RESET; 2168 2169 if (DeviceExtension->InterruptData.Flags & SCSI_PORT_RESET_REQUEST) 2170 { 2171 DeviceExtension->InterruptData.Flags &= ~SCSI_PORT_RESET_REQUEST; 2172 ScsiPortStartPacket(ServiceContext); 2173 } 2174 2175 return FALSE; 2176 } 2177 else 2178 { 2179 DPRINT("Resetting the bus\n"); 2180 2181 for (Bus = 0; Bus < DeviceExtension->NumberOfBuses; Bus++) 2182 { 2183 DeviceExtension->HwResetBus(DeviceExtension->MiniPortDeviceExtension, Bus); 2184 2185 /* Reset flags and set reset timeout to 4 seconds */ 2186 DeviceExtension->InterruptData.Flags |= SCSI_PORT_RESET; 2187 DeviceExtension->TimerCount = 4; 2188 } 2189 2190 /* If miniport requested - request a dpc for it */ 2191 if (DeviceExtension->InterruptData.Flags & SCSI_PORT_NOTIFICATION_NEEDED) 2192 IoRequestDpc(DeviceExtension->Common.DeviceObject, NULL, NULL); 2193 } 2194 2195 return TRUE; 2196 } 2197 2198 2199 BOOLEAN 2200 NTAPI 2201 SpiResetBus(PVOID ServiceContext) 2202 { 2203 PRESETBUS_PARAMS ResetParams = (PRESETBUS_PARAMS)ServiceContext; 2204 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension; 2205 2206 /* Perform the bus reset */ 2207 DeviceExtension = (PSCSI_PORT_DEVICE_EXTENSION)ResetParams->DeviceExtension; 2208 DeviceExtension->HwResetBus(DeviceExtension->MiniPortDeviceExtension, 2209 ResetParams->PathId); 2210 2211 /* Set flags and start the timer */ 2212 DeviceExtension->InterruptData.Flags |= SCSI_PORT_RESET; 2213 DeviceExtension->TimerCount = 4; 2214 2215 /* If miniport requested - give him a DPC */ 2216 if (DeviceExtension->InterruptData.Flags & SCSI_PORT_NOTIFICATION_NEEDED) 2217 IoRequestDpc(DeviceExtension->Common.DeviceObject, NULL, NULL); 2218 2219 return TRUE; 2220 } 2221 2222 // ScsiPortIoTimer 2223 // DESCRIPTION: 2224 // This function handles timeouts and other time delayed processing 2225 // 2226 // RUN LEVEL: 2227 // 2228 // ARGUMENTS: 2229 // IN PDEVICE_OBJECT DeviceObject Device object registered with timer 2230 // IN PVOID Context the Controller extension for the 2231 // controller the device is on 2232 // 2233 static VOID NTAPI 2234 ScsiPortIoTimer(PDEVICE_OBJECT DeviceObject, 2235 PVOID Context) 2236 { 2237 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension; 2238 PSCSI_PORT_LUN_EXTENSION LunExtension; 2239 PIRP Irp; 2240 2241 DPRINT("ScsiPortIoTimer()\n"); 2242 2243 DeviceExtension = (PSCSI_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 2244 2245 /* Protect with the spinlock */ 2246 KeAcquireSpinLockAtDpcLevel(&DeviceExtension->SpinLock); 2247 2248 /* Check timeouts */ 2249 if (DeviceExtension->TimerCount > 0) 2250 { 2251 /* Decrease the timeout counter */ 2252 DeviceExtension->TimerCount--; 2253 2254 if (DeviceExtension->TimerCount == 0) 2255 { 2256 /* Timeout, process it */ 2257 if (KeSynchronizeExecution(DeviceExtension->Interrupt[0], 2258 SpiProcessTimeout, 2259 DeviceExtension->Common.DeviceObject)) 2260 { 2261 DPRINT("Error happened during processing timeout, but nothing critical\n"); 2262 } 2263 } 2264 2265 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock); 2266 2267 /* We should exit now, since timeout is processed */ 2268 return; 2269 } 2270 2271 /* Per-Lun scanning of timeouts is needed... */ 2272 for (UINT8 pathId = 0; pathId < DeviceExtension->NumberOfBuses; pathId++) 2273 { 2274 PSCSI_BUS_INFO bus = &DeviceExtension->Buses[pathId]; 2275 2276 for (PLIST_ENTRY lunEntry = bus->LunsListHead.Flink; 2277 lunEntry != &bus->LunsListHead; 2278 lunEntry = lunEntry->Flink) 2279 { 2280 LunExtension = CONTAINING_RECORD(lunEntry, SCSI_PORT_LUN_EXTENSION, LunEntry); 2281 2282 if (LunExtension->Flags & LUNEX_BUSY) 2283 { 2284 if (!(LunExtension->Flags & 2285 (LUNEX_NEED_REQUEST_SENSE | LUNEX_FROZEN_QUEUE))) 2286 { 2287 DPRINT("Retrying busy request\n"); 2288 2289 /* Clear flags, and retry busy request */ 2290 LunExtension->Flags &= ~(LUNEX_BUSY | LUNEX_FULL_QUEUE); 2291 Irp = LunExtension->BusyRequest; 2292 2293 /* Clearing busy request */ 2294 LunExtension->BusyRequest = NULL; 2295 2296 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock); 2297 2298 IoStartPacket(DeviceObject, Irp, (PULONG)NULL, NULL); 2299 2300 KeAcquireSpinLockAtDpcLevel(&DeviceExtension->SpinLock); 2301 } 2302 } 2303 else if (LunExtension->RequestTimeout == 0) 2304 { 2305 RESETBUS_PARAMS ResetParams; 2306 2307 LunExtension->RequestTimeout = -1; 2308 2309 DPRINT("Request timed out, resetting bus\n"); 2310 2311 /* Pass params to the bus reset routine */ 2312 ResetParams.PathId = LunExtension->PathId; 2313 ResetParams.DeviceExtension = DeviceExtension; 2314 2315 if (!KeSynchronizeExecution(DeviceExtension->Interrupt[0], 2316 SpiResetBus, 2317 &ResetParams)) 2318 { 2319 DPRINT1("Reset failed\n"); 2320 } 2321 } 2322 else if (LunExtension->RequestTimeout > 0) 2323 { 2324 /* Decrement the timeout counter */ 2325 LunExtension->RequestTimeout--; 2326 } 2327 } 2328 } 2329 2330 /* Release the spinlock */ 2331 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock); 2332 } 2333 2334 VOID 2335 NTAPI 2336 SpiMiniportTimerDpc(IN struct _KDPC *Dpc, 2337 IN PVOID DeviceObject, 2338 IN PVOID SystemArgument1, 2339 IN PVOID SystemArgument2) 2340 { 2341 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension; 2342 2343 DPRINT("Miniport timer DPC\n"); 2344 2345 DeviceExtension = ((PDEVICE_OBJECT)DeviceObject)->DeviceExtension; 2346 2347 /* Acquire the spinlock */ 2348 KeAcquireSpinLockAtDpcLevel(&DeviceExtension->SpinLock); 2349 2350 /* Call the timer routine */ 2351 if (DeviceExtension->HwScsiTimer != NULL) 2352 { 2353 DeviceExtension->HwScsiTimer(&DeviceExtension->MiniPortDeviceExtension); 2354 } 2355 2356 /* Release the spinlock */ 2357 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock); 2358 2359 if (DeviceExtension->InterruptData.Flags & SCSI_PORT_NOTIFICATION_NEEDED) 2360 { 2361 ScsiPortDpcForIsr(NULL, 2362 DeviceExtension->Common.DeviceObject, 2363 NULL, 2364 NULL); 2365 } 2366 } 2367 2368 static NTSTATUS 2369 SpiCreatePortConfig(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension, 2370 PHW_INITIALIZATION_DATA HwInitData, 2371 PCONFIGURATION_INFO InternalConfigInfo, 2372 PPORT_CONFIGURATION_INFORMATION ConfigInfo, 2373 BOOLEAN ZeroStruct) 2374 { 2375 UNICODE_STRING UnicodeString; 2376 OBJECT_ATTRIBUTES ObjectAttributes; 2377 PCONFIGURATION_INFORMATION DdkConfigInformation; 2378 HANDLE RootKey, Key; 2379 BOOLEAN Found; 2380 WCHAR DeviceBuffer[16]; 2381 WCHAR StrBuffer[512]; 2382 ULONG Bus; 2383 NTSTATUS Status; 2384 2385 /* Zero out the struct if told so */ 2386 if (ZeroStruct) 2387 { 2388 /* First zero the portconfig */ 2389 RtlZeroMemory(ConfigInfo, sizeof(PORT_CONFIGURATION_INFORMATION)); 2390 2391 /* Then access ranges */ 2392 RtlZeroMemory(InternalConfigInfo->AccessRanges, 2393 HwInitData->NumberOfAccessRanges * sizeof(ACCESS_RANGE)); 2394 2395 /* Initialize the struct */ 2396 ConfigInfo->Length = sizeof(PORT_CONFIGURATION_INFORMATION); 2397 ConfigInfo->AdapterInterfaceType = HwInitData->AdapterInterfaceType; 2398 ConfigInfo->InterruptMode = Latched; 2399 ConfigInfo->DmaChannel = SP_UNINITIALIZED_VALUE; 2400 ConfigInfo->DmaPort = SP_UNINITIALIZED_VALUE; 2401 ConfigInfo->DmaChannel2 = SP_UNINITIALIZED_VALUE; 2402 ConfigInfo->DmaPort2 = SP_UNINITIALIZED_VALUE; 2403 ConfigInfo->MaximumTransferLength = SP_UNINITIALIZED_VALUE; 2404 ConfigInfo->NumberOfAccessRanges = HwInitData->NumberOfAccessRanges; 2405 ConfigInfo->MaximumNumberOfTargets = 8; 2406 2407 /* Store parameters */ 2408 ConfigInfo->NeedPhysicalAddresses = HwInitData->NeedPhysicalAddresses; 2409 ConfigInfo->MapBuffers = HwInitData->MapBuffers; 2410 ConfigInfo->AutoRequestSense = HwInitData->AutoRequestSense; 2411 ConfigInfo->ReceiveEvent = HwInitData->ReceiveEvent; 2412 ConfigInfo->TaggedQueuing = HwInitData->TaggedQueuing; 2413 ConfigInfo->MultipleRequestPerLu = HwInitData->MultipleRequestPerLu; 2414 2415 /* Get the disk usage */ 2416 DdkConfigInformation = IoGetConfigurationInformation(); 2417 ConfigInfo->AtdiskPrimaryClaimed = DdkConfigInformation->AtDiskPrimaryAddressClaimed; 2418 ConfigInfo->AtdiskSecondaryClaimed = DdkConfigInformation->AtDiskSecondaryAddressClaimed; 2419 2420 /* Initiator bus id is not set */ 2421 for (Bus = 0; Bus < 8; Bus++) 2422 ConfigInfo->InitiatorBusId[Bus] = (CCHAR)SP_UNINITIALIZED_VALUE; 2423 } 2424 2425 ConfigInfo->NumberOfPhysicalBreaks = 17; 2426 2427 /* Clear this information */ 2428 InternalConfigInfo->DisableTaggedQueueing = FALSE; 2429 InternalConfigInfo->DisableMultipleLun = FALSE; 2430 2431 /* Store Bus Number */ 2432 ConfigInfo->SystemIoBusNumber = InternalConfigInfo->BusNumber; 2433 2434 TryNextAd: 2435 2436 if (ConfigInfo->AdapterInterfaceType == Internal) 2437 { 2438 /* Open registry key for HW database */ 2439 InitializeObjectAttributes(&ObjectAttributes, 2440 DeviceExtension->Common.DeviceObject->DriverObject->HardwareDatabase, 2441 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 2442 NULL, 2443 NULL); 2444 2445 Status = ZwOpenKey(&RootKey, 2446 KEY_READ, 2447 &ObjectAttributes); 2448 2449 if (NT_SUCCESS(Status)) 2450 { 2451 /* Create name for it */ 2452 swprintf(StrBuffer, L"ScsiAdapter\\%lu", 2453 InternalConfigInfo->AdapterNumber); 2454 2455 RtlInitUnicodeString(&UnicodeString, StrBuffer); 2456 2457 /* Open device key */ 2458 InitializeObjectAttributes(&ObjectAttributes, 2459 &UnicodeString, 2460 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 2461 RootKey, 2462 NULL); 2463 2464 Status = ZwOpenKey(&Key, 2465 KEY_READ, 2466 &ObjectAttributes); 2467 2468 ZwClose(RootKey); 2469 2470 if (NT_SUCCESS(Status)) 2471 { 2472 if (InternalConfigInfo->LastAdapterNumber != InternalConfigInfo->AdapterNumber) 2473 { 2474 DPRINT("Hardware info found at %S\n", StrBuffer); 2475 2476 /* Parse it */ 2477 SpiParseDeviceInfo(DeviceExtension, 2478 Key, 2479 ConfigInfo, 2480 InternalConfigInfo, 2481 (PUCHAR)StrBuffer); 2482 2483 InternalConfigInfo->BusNumber = 0; 2484 } 2485 else 2486 { 2487 /* Try the next adapter */ 2488 InternalConfigInfo->AdapterNumber++; 2489 goto TryNextAd; 2490 } 2491 } 2492 else 2493 { 2494 /* Info was not found, exit */ 2495 DPRINT("ZwOpenKey() failed with Status=0x%08X\n", Status); 2496 return STATUS_DEVICE_DOES_NOT_EXIST; 2497 } 2498 } 2499 else 2500 { 2501 DPRINT1("ZwOpenKey() failed with Status=0x%08X\n", Status); 2502 } 2503 } 2504 2505 /* Look at device params */ 2506 Key = NULL; 2507 if (InternalConfigInfo->Parameter) 2508 { 2509 ExFreePool(InternalConfigInfo->Parameter); 2510 InternalConfigInfo->Parameter = NULL; 2511 } 2512 2513 if (InternalConfigInfo->ServiceKey != NULL) 2514 { 2515 swprintf(DeviceBuffer, L"Device%lu", InternalConfigInfo->AdapterNumber); 2516 RtlInitUnicodeString(&UnicodeString, DeviceBuffer); 2517 2518 /* Open the service key */ 2519 InitializeObjectAttributes(&ObjectAttributes, 2520 &UnicodeString, 2521 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 2522 InternalConfigInfo->ServiceKey, 2523 NULL); 2524 2525 Status = ZwOpenKey(&Key, 2526 KEY_READ, 2527 &ObjectAttributes); 2528 } 2529 2530 /* Parse device key */ 2531 if (InternalConfigInfo->DeviceKey != NULL) 2532 { 2533 SpiParseDeviceInfo(DeviceExtension, 2534 InternalConfigInfo->DeviceKey, 2535 ConfigInfo, 2536 InternalConfigInfo, 2537 (PUCHAR)StrBuffer); 2538 } 2539 2540 /* Then parse hw info */ 2541 if (Key != NULL) 2542 { 2543 if (InternalConfigInfo->LastAdapterNumber != InternalConfigInfo->AdapterNumber) 2544 { 2545 SpiParseDeviceInfo(DeviceExtension, 2546 Key, 2547 ConfigInfo, 2548 InternalConfigInfo, 2549 (PUCHAR)StrBuffer); 2550 2551 /* Close the key */ 2552 ZwClose(Key); 2553 } 2554 else 2555 { 2556 /* Adapter not found, go try the next one */ 2557 InternalConfigInfo->AdapterNumber++; 2558 2559 /* Close the key */ 2560 ZwClose(Key); 2561 2562 goto TryNextAd; 2563 } 2564 } 2565 2566 /* Update the last adapter number */ 2567 InternalConfigInfo->LastAdapterNumber = InternalConfigInfo->AdapterNumber; 2568 2569 /* Do we have this kind of bus at all? */ 2570 Found = FALSE; 2571 Status = IoQueryDeviceDescription(&HwInitData->AdapterInterfaceType, 2572 &InternalConfigInfo->BusNumber, 2573 NULL, 2574 NULL, 2575 NULL, 2576 NULL, 2577 SpQueryDeviceCallout, 2578 &Found); 2579 2580 /* This bus was not found */ 2581 if (!Found) 2582 { 2583 INTERFACE_TYPE InterfaceType = Eisa; 2584 2585 /* Check for EISA */ 2586 if (HwInitData->AdapterInterfaceType == Isa) 2587 { 2588 Status = IoQueryDeviceDescription(&InterfaceType, 2589 &InternalConfigInfo->BusNumber, 2590 NULL, 2591 NULL, 2592 NULL, 2593 NULL, 2594 SpQueryDeviceCallout, 2595 &Found); 2596 2597 /* Return respectively */ 2598 if (Found) 2599 return STATUS_SUCCESS; 2600 else 2601 return STATUS_DEVICE_DOES_NOT_EXIST; 2602 } 2603 else 2604 { 2605 return STATUS_DEVICE_DOES_NOT_EXIST; 2606 } 2607 } 2608 else 2609 { 2610 return STATUS_SUCCESS; 2611 } 2612 } 2613 2614 static VOID 2615 SpiParseDeviceInfo(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension, 2616 IN HANDLE Key, 2617 IN PPORT_CONFIGURATION_INFORMATION ConfigInfo, 2618 IN PCONFIGURATION_INFO InternalConfigInfo, 2619 IN PUCHAR Buffer) 2620 { 2621 PKEY_VALUE_FULL_INFORMATION KeyValueInformation; 2622 PCM_FULL_RESOURCE_DESCRIPTOR FullResource; 2623 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor; 2624 PCM_SCSI_DEVICE_DATA ScsiDeviceData; 2625 ULONG Length, Count, Dma = 0, Interrupt = 0; 2626 ULONG Index = 0, RangeCount = 0; 2627 UNICODE_STRING UnicodeString; 2628 ANSI_STRING AnsiString; 2629 NTSTATUS Status = STATUS_SUCCESS; 2630 2631 2632 KeyValueInformation = (PKEY_VALUE_FULL_INFORMATION) Buffer; 2633 2634 /* Loop through all values in the device node */ 2635 while(TRUE) 2636 { 2637 Status = ZwEnumerateValueKey(Key, 2638 Index, 2639 KeyValueFullInformation, 2640 Buffer, 2641 512, 2642 &Length); 2643 2644 if (!NT_SUCCESS(Status)) 2645 return; 2646 2647 Index++; 2648 2649 /* Length for DWORD is ok? */ 2650 if (KeyValueInformation->Type == REG_DWORD && 2651 KeyValueInformation->DataLength != sizeof(ULONG)) 2652 { 2653 continue; 2654 } 2655 2656 /* Get MaximumLogicalUnit */ 2657 if (_wcsnicmp(KeyValueInformation->Name, L"MaximumLogicalUnit", 2658 KeyValueInformation->NameLength/2) == 0) 2659 { 2660 2661 if (KeyValueInformation->Type != REG_DWORD) 2662 { 2663 DPRINT("Bad data type for MaximumLogicalUnit\n"); 2664 continue; 2665 } 2666 2667 DeviceExtension->MaxLunCount = *((PUCHAR) 2668 (Buffer + KeyValueInformation->DataOffset)); 2669 2670 /* Check / reset if needed */ 2671 if (DeviceExtension->MaxLunCount > SCSI_MAXIMUM_LOGICAL_UNITS) 2672 DeviceExtension->MaxLunCount = SCSI_MAXIMUM_LOGICAL_UNITS; 2673 2674 DPRINT("MaximumLogicalUnit = %d\n", DeviceExtension->MaxLunCount); 2675 } 2676 2677 /* Get InitiatorTargetId */ 2678 if (_wcsnicmp(KeyValueInformation->Name, L"InitiatorTargetId", 2679 KeyValueInformation->NameLength / 2) == 0) 2680 { 2681 2682 if (KeyValueInformation->Type != REG_DWORD) 2683 { 2684 DPRINT("Bad data type for InitiatorTargetId\n"); 2685 continue; 2686 } 2687 2688 ConfigInfo->InitiatorBusId[0] = *((PUCHAR) 2689 (Buffer + KeyValueInformation->DataOffset)); 2690 2691 /* Check / reset if needed */ 2692 if (ConfigInfo->InitiatorBusId[0] > ConfigInfo->MaximumNumberOfTargets - 1) 2693 ConfigInfo->InitiatorBusId[0] = (CCHAR)-1; 2694 2695 DPRINT("InitiatorTargetId = %d\n", ConfigInfo->InitiatorBusId[0]); 2696 } 2697 2698 /* Get ScsiDebug */ 2699 if (_wcsnicmp(KeyValueInformation->Name, L"ScsiDebug", 2700 KeyValueInformation->NameLength/2) == 0) 2701 { 2702 DPRINT("ScsiDebug key not supported\n"); 2703 } 2704 2705 /* Check for a breakpoint */ 2706 if (_wcsnicmp(KeyValueInformation->Name, L"BreakPointOnEntry", 2707 KeyValueInformation->NameLength/2) == 0) 2708 { 2709 DPRINT1("Breakpoint on entry requested!\n"); 2710 DbgBreakPoint(); 2711 } 2712 2713 /* Get DisableSynchronousTransfers */ 2714 if (_wcsnicmp(KeyValueInformation->Name, L"DisableSynchronousTransfers", 2715 KeyValueInformation->NameLength/2) == 0) 2716 { 2717 DeviceExtension->SrbFlags |= SRB_FLAGS_DISABLE_SYNCH_TRANSFER; 2718 DPRINT("Synch transfers disabled\n"); 2719 } 2720 2721 /* Get DisableDisconnects */ 2722 if (_wcsnicmp(KeyValueInformation->Name, L"DisableDisconnects", 2723 KeyValueInformation->NameLength/2) == 0) 2724 { 2725 DeviceExtension->SrbFlags |= SRB_FLAGS_DISABLE_DISCONNECT; 2726 DPRINT("Disconnects disabled\n"); 2727 } 2728 2729 /* Get DisableTaggedQueuing */ 2730 if (_wcsnicmp(KeyValueInformation->Name, L"DisableTaggedQueuing", 2731 KeyValueInformation->NameLength/2) == 0) 2732 { 2733 InternalConfigInfo->DisableTaggedQueueing = TRUE; 2734 DPRINT("Tagged queueing disabled\n"); 2735 } 2736 2737 /* Get DisableMultipleRequests */ 2738 if (_wcsnicmp(KeyValueInformation->Name, L"DisableMultipleRequests", 2739 KeyValueInformation->NameLength/2) == 0) 2740 { 2741 InternalConfigInfo->DisableMultipleLun = TRUE; 2742 DPRINT("Multiple requests disabled\n"); 2743 } 2744 2745 /* Get DriverParameters */ 2746 if (_wcsnicmp(KeyValueInformation->Name, L"DriverParameters", 2747 KeyValueInformation->NameLength/2) == 0) 2748 { 2749 /* Skip if nothing */ 2750 if (KeyValueInformation->DataLength == 0) 2751 continue; 2752 2753 /* If there was something previously allocated - free it */ 2754 if (InternalConfigInfo->Parameter != NULL) 2755 ExFreePool(InternalConfigInfo->Parameter); 2756 2757 /* Allocate it */ 2758 InternalConfigInfo->Parameter = ExAllocatePoolWithTag(NonPagedPool, 2759 KeyValueInformation->DataLength, TAG_SCSIPORT); 2760 2761 if (InternalConfigInfo->Parameter != NULL) 2762 { 2763 if (KeyValueInformation->Type != REG_SZ) 2764 { 2765 /* Just copy */ 2766 RtlCopyMemory( 2767 InternalConfigInfo->Parameter, 2768 (PCCHAR)KeyValueInformation + KeyValueInformation->DataOffset, 2769 KeyValueInformation->DataLength); 2770 } 2771 else 2772 { 2773 /* If it's a unicode string, convert it to ansi */ 2774 UnicodeString.Length = (USHORT)KeyValueInformation->DataLength; 2775 UnicodeString.MaximumLength = (USHORT)KeyValueInformation->DataLength; 2776 UnicodeString.Buffer = 2777 (PWSTR)((PCCHAR)KeyValueInformation + KeyValueInformation->DataOffset); 2778 2779 AnsiString.Length = 0; 2780 AnsiString.MaximumLength = (USHORT)KeyValueInformation->DataLength; 2781 AnsiString.Buffer = (PCHAR)InternalConfigInfo->Parameter; 2782 2783 Status = RtlUnicodeStringToAnsiString(&AnsiString, 2784 &UnicodeString, 2785 FALSE); 2786 2787 /* In case of error, free the allocated space */ 2788 if (!NT_SUCCESS(Status)) 2789 { 2790 ExFreePool(InternalConfigInfo->Parameter); 2791 InternalConfigInfo->Parameter = NULL; 2792 } 2793 2794 } 2795 } 2796 2797 DPRINT("Found driver parameter\n"); 2798 } 2799 2800 /* Get MaximumSGList */ 2801 if (_wcsnicmp(KeyValueInformation->Name, L"MaximumSGList", 2802 KeyValueInformation->NameLength/2) == 0) 2803 { 2804 if (KeyValueInformation->Type != REG_DWORD) 2805 { 2806 DPRINT("Bad data type for MaximumSGList\n"); 2807 continue; 2808 } 2809 2810 ConfigInfo->NumberOfPhysicalBreaks = *((PUCHAR)(Buffer + KeyValueInformation->DataOffset)); 2811 2812 /* Check / fix */ 2813 if (ConfigInfo->NumberOfPhysicalBreaks > SCSI_MAXIMUM_PHYSICAL_BREAKS) 2814 { 2815 ConfigInfo->NumberOfPhysicalBreaks = SCSI_MAXIMUM_PHYSICAL_BREAKS; 2816 } 2817 else if (ConfigInfo->NumberOfPhysicalBreaks < SCSI_MINIMUM_PHYSICAL_BREAKS) 2818 { 2819 ConfigInfo->NumberOfPhysicalBreaks = SCSI_MINIMUM_PHYSICAL_BREAKS; 2820 } 2821 2822 DPRINT("MaximumSGList = %d\n", ConfigInfo->NumberOfPhysicalBreaks); 2823 } 2824 2825 /* Get NumberOfRequests */ 2826 if (_wcsnicmp(KeyValueInformation->Name, L"NumberOfRequests", 2827 KeyValueInformation->NameLength/2) == 0) 2828 { 2829 if (KeyValueInformation->Type != REG_DWORD) 2830 { 2831 DPRINT("NumberOfRequests has wrong data type\n"); 2832 continue; 2833 } 2834 2835 DeviceExtension->RequestsNumber = *((PUCHAR)(Buffer + KeyValueInformation->DataOffset)); 2836 2837 /* Check / fix */ 2838 if (DeviceExtension->RequestsNumber < 16) 2839 { 2840 DeviceExtension->RequestsNumber = 16; 2841 } 2842 else if (DeviceExtension->RequestsNumber > 512) 2843 { 2844 DeviceExtension->RequestsNumber = 512; 2845 } 2846 2847 DPRINT("Number Of Requests = %d\n", DeviceExtension->RequestsNumber); 2848 } 2849 2850 /* Get resource list */ 2851 if (_wcsnicmp(KeyValueInformation->Name, L"ResourceList", 2852 KeyValueInformation->NameLength/2) == 0 || 2853 _wcsnicmp(KeyValueInformation->Name, L"Configuration Data", 2854 KeyValueInformation->NameLength/2) == 0 ) 2855 { 2856 if (KeyValueInformation->Type != REG_FULL_RESOURCE_DESCRIPTOR || 2857 KeyValueInformation->DataLength < sizeof(REG_FULL_RESOURCE_DESCRIPTOR)) 2858 { 2859 DPRINT("Bad data type for ResourceList\n"); 2860 continue; 2861 } 2862 else 2863 { 2864 DPRINT("Found ResourceList\n"); 2865 } 2866 2867 FullResource = (PCM_FULL_RESOURCE_DESCRIPTOR)(Buffer + KeyValueInformation->DataOffset); 2868 2869 /* Copy some info from it */ 2870 InternalConfigInfo->BusNumber = FullResource->BusNumber; 2871 ConfigInfo->SystemIoBusNumber = FullResource->BusNumber; 2872 2873 /* Loop through it */ 2874 for (Count = 0; Count < FullResource->PartialResourceList.Count; Count++) 2875 { 2876 /* Get partial descriptor */ 2877 PartialDescriptor = 2878 &FullResource->PartialResourceList.PartialDescriptors[Count]; 2879 2880 /* Check datalength */ 2881 if ((ULONG)((PCHAR)(PartialDescriptor + 1) - 2882 (PCHAR)FullResource) > KeyValueInformation->DataLength) 2883 { 2884 DPRINT("Resource data is of incorrect size\n"); 2885 break; 2886 } 2887 2888 switch (PartialDescriptor->Type) 2889 { 2890 case CmResourceTypePort: 2891 if (RangeCount >= ConfigInfo->NumberOfAccessRanges) 2892 { 2893 DPRINT("Too many access ranges\n"); 2894 continue; 2895 } 2896 2897 InternalConfigInfo->AccessRanges[RangeCount].RangeInMemory = FALSE; 2898 InternalConfigInfo->AccessRanges[RangeCount].RangeStart = PartialDescriptor->u.Port.Start; 2899 InternalConfigInfo->AccessRanges[RangeCount].RangeLength = PartialDescriptor->u.Port.Length; 2900 RangeCount++; 2901 2902 break; 2903 2904 case CmResourceTypeMemory: 2905 if (RangeCount >= ConfigInfo->NumberOfAccessRanges) 2906 { 2907 DPRINT("Too many access ranges\n"); 2908 continue; 2909 } 2910 2911 InternalConfigInfo->AccessRanges[RangeCount].RangeInMemory = TRUE; 2912 InternalConfigInfo->AccessRanges[RangeCount].RangeStart = PartialDescriptor->u.Memory.Start; 2913 InternalConfigInfo->AccessRanges[RangeCount].RangeLength = PartialDescriptor->u.Memory.Length; 2914 RangeCount++; 2915 2916 break; 2917 2918 case CmResourceTypeInterrupt: 2919 2920 if (Interrupt == 0) 2921 { 2922 ConfigInfo->BusInterruptLevel = 2923 PartialDescriptor->u.Interrupt.Level; 2924 2925 ConfigInfo->BusInterruptVector = 2926 PartialDescriptor->u.Interrupt.Vector; 2927 2928 ConfigInfo->InterruptMode = (PartialDescriptor->Flags & CM_RESOURCE_INTERRUPT_LATCHED) ? Latched : LevelSensitive; 2929 } 2930 else if (Interrupt == 1) 2931 { 2932 ConfigInfo->BusInterruptLevel2 = 2933 PartialDescriptor->u.Interrupt.Level; 2934 2935 ConfigInfo->BusInterruptVector2 = 2936 PartialDescriptor->u.Interrupt.Vector; 2937 2938 ConfigInfo->InterruptMode2 = (PartialDescriptor->Flags & CM_RESOURCE_INTERRUPT_LATCHED) ? Latched : LevelSensitive; 2939 } 2940 2941 Interrupt++; 2942 break; 2943 2944 case CmResourceTypeDma: 2945 2946 if (Dma == 0) 2947 { 2948 ConfigInfo->DmaChannel = PartialDescriptor->u.Dma.Channel; 2949 ConfigInfo->DmaPort = PartialDescriptor->u.Dma.Port; 2950 2951 if (PartialDescriptor->Flags & CM_RESOURCE_DMA_8) 2952 ConfigInfo->DmaWidth = Width8Bits; 2953 else if ((PartialDescriptor->Flags & CM_RESOURCE_DMA_16) || 2954 (PartialDescriptor->Flags & CM_RESOURCE_DMA_8_AND_16)) //??? 2955 ConfigInfo->DmaWidth = Width16Bits; 2956 else if (PartialDescriptor->Flags & CM_RESOURCE_DMA_32) 2957 ConfigInfo->DmaWidth = Width32Bits; 2958 } 2959 else if (Dma == 1) 2960 { 2961 ConfigInfo->DmaChannel2 = PartialDescriptor->u.Dma.Channel; 2962 ConfigInfo->DmaPort2 = PartialDescriptor->u.Dma.Port; 2963 2964 if (PartialDescriptor->Flags & CM_RESOURCE_DMA_8) 2965 ConfigInfo->DmaWidth2 = Width8Bits; 2966 else if ((PartialDescriptor->Flags & CM_RESOURCE_DMA_16) || 2967 (PartialDescriptor->Flags & CM_RESOURCE_DMA_8_AND_16)) //??? 2968 ConfigInfo->DmaWidth2 = Width16Bits; 2969 else if (PartialDescriptor->Flags & CM_RESOURCE_DMA_32) 2970 ConfigInfo->DmaWidth2 = Width32Bits; 2971 } 2972 2973 Dma++; 2974 break; 2975 2976 case CmResourceTypeDeviceSpecific: 2977 if (PartialDescriptor->u.DeviceSpecificData.DataSize < 2978 sizeof(CM_SCSI_DEVICE_DATA) || 2979 (PCHAR) (PartialDescriptor + 1) - (PCHAR)FullResource + 2980 PartialDescriptor->u.DeviceSpecificData.DataSize > 2981 KeyValueInformation->DataLength) 2982 { 2983 DPRINT("Resource data length is incorrect"); 2984 break; 2985 } 2986 2987 /* Set only one field from it */ 2988 ScsiDeviceData = (PCM_SCSI_DEVICE_DATA) (PartialDescriptor+1); 2989 ConfigInfo->InitiatorBusId[0] = ScsiDeviceData->HostIdentifier; 2990 break; 2991 } 2992 } 2993 } 2994 } 2995 } 2996 2997 NTSTATUS 2998 NTAPI 2999 SpQueryDeviceCallout(IN PVOID Context, 3000 IN PUNICODE_STRING PathName, 3001 IN INTERFACE_TYPE BusType, 3002 IN ULONG BusNumber, 3003 IN PKEY_VALUE_FULL_INFORMATION *BusInformation, 3004 IN CONFIGURATION_TYPE ControllerType, 3005 IN ULONG ControllerNumber, 3006 IN PKEY_VALUE_FULL_INFORMATION *ControllerInformation, 3007 IN CONFIGURATION_TYPE PeripheralType, 3008 IN ULONG PeripheralNumber, 3009 IN PKEY_VALUE_FULL_INFORMATION *PeripheralInformation) 3010 { 3011 PBOOLEAN Found = (PBOOLEAN)Context; 3012 /* We just set our Found variable to TRUE */ 3013 3014 *Found = TRUE; 3015 return STATUS_SUCCESS; 3016 } 3017 3018 IO_ALLOCATION_ACTION 3019 NTAPI 3020 ScsiPortAllocateAdapterChannel(IN PDEVICE_OBJECT DeviceObject, 3021 IN PIRP Irp, 3022 IN PVOID MapRegisterBase, 3023 IN PVOID Context) 3024 { 3025 KIRQL Irql; 3026 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension; 3027 3028 /* Guard access with the spinlock */ 3029 KeAcquireSpinLock(&DeviceExtension->SpinLock, &Irql); 3030 3031 /* Save MapRegisterBase we've got here */ 3032 DeviceExtension->MapRegisterBase = MapRegisterBase; 3033 3034 /* Start pending request */ 3035 KeSynchronizeExecution(DeviceExtension->Interrupt[0], 3036 ScsiPortStartPacket, DeviceObject); 3037 3038 /* Release spinlock we took */ 3039 KeReleaseSpinLock(&DeviceExtension->SpinLock, Irql); 3040 3041 return KeepObject; 3042 } 3043 3044 #undef ScsiPortConvertPhysicalAddressToUlong 3045 /* 3046 * @implemented 3047 */ 3048 ULONG NTAPI 3049 ScsiPortConvertPhysicalAddressToUlong(IN SCSI_PHYSICAL_ADDRESS Address) 3050 { 3051 DPRINT("ScsiPortConvertPhysicalAddressToUlong()\n"); 3052 return(Address.u.LowPart); 3053 } 3054