3 * Copyright (C) 2001, 2002 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS kernel
23 * FILE: services/storage/scsiport/scsiport.c
24 * PURPOSE: SCSI port driver
25 * PROGRAMMER: Eric Kohl (ekohl@rz-online.de)
29 /* INCLUDES *****************************************************************/
31 #include <ddk/ntddk.h>
34 #include <ddk/ntddscsi.h>
35 #include <ddk/ntddstor.h>
36 #include <ddk/ntdddisk.h>
42 #include "scsiport_int.h"
44 /* TYPES *********************************************************************/
46 #define IRP_FLAG_COMPLETE 0x00000001
47 #define IRP_FLAG_NEXT 0x00000002
48 #define IRP_FLAG_NEXT_LU 0x00000004
50 /* GLOBALS *******************************************************************/
52 static ULONG InternalDebugLevel
= 0;
55 SpiProcessRequests(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
59 SpiStartIo(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
63 SpiGetPciConfigData (IN
struct _HW_INITIALIZATION_DATA
*HwInitializationData
,
64 IN OUT PPORT_CONFIGURATION_INFORMATION PortConfig
,
66 IN OUT PPCI_SLOT_NUMBER NextSlotNumber
);
68 static NTSTATUS STDCALL
69 ScsiPortCreateClose(IN PDEVICE_OBJECT DeviceObject
,
72 static NTSTATUS STDCALL
73 ScsiPortDispatchScsi(IN PDEVICE_OBJECT DeviceObject
,
76 static NTSTATUS STDCALL
77 ScsiPortDeviceControl(IN PDEVICE_OBJECT DeviceObject
,
80 static BOOLEAN STDCALL
81 ScsiPortStartPacket(IN OUT PVOID Context
);
84 static PSCSI_PORT_LUN_EXTENSION
85 SpiAllocateLunExtension (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
91 SpiRemoveLunExtension (IN PSCSI_PORT_LUN_EXTENSION LunExtension
);
93 static PSCSI_PORT_LUN_EXTENSION
94 SpiGetLunExtension (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
100 SpiSendInquiry (IN PDEVICE_OBJECT DeviceObject
,
101 IN OUT PSCSI_REQUEST_BLOCK Srb
,
102 IN OUT PIO_STATUS_BLOCK IoStatusBlock
,
103 IN OUT PKEVENT Event
);
106 SpiScanAdapter (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
);
109 SpiGetInquiryData (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
110 OUT PSCSI_ADAPTER_BUS_INFO AdapterBusInfo
);
112 static BOOLEAN STDCALL
113 ScsiPortIsr(IN PKINTERRUPT Interrupt
,
114 IN PVOID ServiceContext
);
117 ScsiPortDpc(IN PKDPC Dpc
,
118 IN PDEVICE_OBJECT DpcDeviceObject
,
120 IN PVOID DpcContext
);
123 ScsiPortIoTimer(PDEVICE_OBJECT DeviceObject
,
126 static PSCSI_REQUEST_BLOCK
127 ScsiPortInitSenseRequestSrb(PSCSI_REQUEST_BLOCK OriginalSrb
);
130 SpiBuildDeviceMap (PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
131 PUNICODE_STRING RegistryPath
);
134 SpiAllocateSrbExtension(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
135 PSCSI_REQUEST_BLOCK Srb
);
138 SpiFreeSrbExtension(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
139 PSCSI_REQUEST_BLOCK Srb
);
143 SpiScsiMiniport(IN PDEVICE_OBJECT DeviceObject
,
146 /* FUNCTIONS *****************************************************************/
148 /**********************************************************************
153 * This function initializes the driver.
160 * System allocated Driver Object for this driver.
163 * Name of registry driver service key.
170 DriverEntry(IN PDRIVER_OBJECT DriverObject
,
171 IN PUNICODE_STRING RegistryPath
)
173 DPRINT("ScsiPort Driver %s\n", VERSION
);
174 return(STATUS_SUCCESS
);
178 /**********************************************************************
183 * Prints debugging messages.
190 * Debug level of the given message.
193 * Pointer to printf()-compatible format string.
196 Additional output data (see printf()).
205 ScsiDebugPrint(IN ULONG DebugPrintLevel
,
206 IN PCHAR DebugMessage
,
212 if (DebugPrintLevel
>= InternalDebugLevel
)
215 va_start(ap
, DebugMessage
);
216 vsprintf(Buffer
, DebugMessage
, ap
);
227 ScsiPortCompleteRequest(IN PVOID HwDeviceExtension
,
233 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
234 PSCSI_PORT_LUN_EXTENSION LunExtension
;
237 PSCSI_REQUEST_BLOCK Srb
;
239 DPRINT("ScsiPortCompleteRequest(HwDeviceExtension %x, PathId %d, TargetId %d, Lun %d, SrbStatus %x)\n",
240 HwDeviceExtension
, PathId
, TargetId
, Lun
, SrbStatus
);
242 DeviceExtension
= CONTAINING_RECORD(HwDeviceExtension
,
243 SCSI_PORT_DEVICE_EXTENSION
,
244 MiniPortDeviceExtension
);
246 Entry
= DeviceExtension
->LunExtensionListHead
.Flink
;
247 while (Entry
!= &DeviceExtension
->LunExtensionListHead
)
249 LunExtension
= CONTAINING_RECORD(Entry
,
250 SCSI_PORT_LUN_EXTENSION
,
255 if (PathId
== (UCHAR
)SP_UNTAGGED
||
256 (PathId
== LunExtension
->PathId
&& TargetId
== (UCHAR
)SP_UNTAGGED
) ||
257 (PathId
== LunExtension
->PathId
&& TargetId
== LunExtension
->TargetId
&& Lun
== (UCHAR
)SP_UNTAGGED
) ||
258 (PathId
== LunExtension
->PathId
&& TargetId
== LunExtension
->TargetId
&& Lun
== LunExtension
->Lun
))
260 Irp
= LunExtension
->NextIrp
;
263 Srb
= (PSCSI_REQUEST_BLOCK
)Irp
->Tail
.Overlay
.DriverContext
[3];
264 if (Srb
->SrbFlags
& SRB_FLAGS_IS_ACTIVE
)
266 Srb
->SrbStatus
= SrbStatus
;
267 ScsiPortNotification(RequestComplete
,
271 Irp
= Irp
->Tail
.Overlay
.DriverContext
[1];
274 Entry
= Entry
->Flink
;
282 #undef ScsiPortConvertPhysicalAddressToUlong
284 ScsiPortConvertPhysicalAddressToUlong(IN SCSI_PHYSICAL_ADDRESS Address
)
286 DPRINT("ScsiPortConvertPhysicalAddressToUlong()\n");
287 return(Address
.u
.LowPart
);
295 ScsiPortFlushDma(IN PVOID HwDeviceExtension
)
297 DPRINT("ScsiPortFlushDma()\n");
306 ScsiPortFreeDeviceBase(IN PVOID HwDeviceExtension
,
307 IN PVOID MappedAddress
)
309 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
310 PSCSI_PORT_DEVICE_BASE DeviceBase
;
313 DPRINT("ScsiPortFreeDeviceBase() called\n");
315 DeviceExtension
= CONTAINING_RECORD(HwDeviceExtension
,
316 SCSI_PORT_DEVICE_EXTENSION
,
317 MiniPortDeviceExtension
);
318 if (IsListEmpty(&DeviceExtension
->DeviceBaseListHead
))
321 Entry
= DeviceExtension
->DeviceBaseListHead
.Flink
;
322 while (Entry
!= &DeviceExtension
->DeviceBaseListHead
)
324 DeviceBase
= CONTAINING_RECORD(Entry
,
325 SCSI_PORT_DEVICE_BASE
,
327 if (DeviceBase
->MappedAddress
== MappedAddress
)
329 MmUnmapIoSpace(DeviceBase
->MappedAddress
,
330 DeviceBase
->NumberOfBytes
);
331 RemoveEntryList(Entry
);
332 ExFreePool(DeviceBase
);
337 Entry
= Entry
->Flink
;
346 ScsiPortGetBusData(IN PVOID DeviceExtension
,
347 IN ULONG BusDataType
,
348 IN ULONG SystemIoBusNumber
,
353 return(HalGetBusData(BusDataType
,
365 ScsiPortGetDeviceBase(IN PVOID HwDeviceExtension
,
366 IN INTERFACE_TYPE BusType
,
367 IN ULONG SystemIoBusNumber
,
368 IN SCSI_PHYSICAL_ADDRESS IoAddress
,
369 IN ULONG NumberOfBytes
,
370 IN BOOLEAN InIoSpace
)
372 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
373 PHYSICAL_ADDRESS TranslatedAddress
;
374 PSCSI_PORT_DEVICE_BASE DeviceBase
;
378 DPRINT ("ScsiPortGetDeviceBase() called\n");
380 AddressSpace
= (ULONG
)InIoSpace
;
381 if (HalTranslateBusAddress(BusType
,
385 &TranslatedAddress
) == FALSE
)
389 if (AddressSpace
!= 0)
390 return((PVOID
)TranslatedAddress
.u
.LowPart
);
392 MappedAddress
= MmMapIoSpace(TranslatedAddress
,
396 DeviceBase
= ExAllocatePool(NonPagedPool
,
397 sizeof(SCSI_PORT_DEVICE_BASE
));
398 if (DeviceBase
== NULL
)
399 return(MappedAddress
);
401 DeviceBase
->MappedAddress
= MappedAddress
;
402 DeviceBase
->NumberOfBytes
= NumberOfBytes
;
403 DeviceBase
->IoAddress
= IoAddress
;
404 DeviceBase
->SystemIoBusNumber
= SystemIoBusNumber
;
406 DeviceExtension
= CONTAINING_RECORD(HwDeviceExtension
,
407 SCSI_PORT_DEVICE_EXTENSION
,
408 MiniPortDeviceExtension
);
410 InsertHeadList(&DeviceExtension
->DeviceBaseListHead
,
413 return(MappedAddress
);
421 ScsiPortGetLogicalUnit(IN PVOID HwDeviceExtension
,
426 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
427 PSCSI_PORT_LUN_EXTENSION LunExtension
;
430 DPRINT("ScsiPortGetLogicalUnit() called\n");
432 DeviceExtension
= CONTAINING_RECORD(HwDeviceExtension
,
433 SCSI_PORT_DEVICE_EXTENSION
,
434 MiniPortDeviceExtension
);
435 if (IsListEmpty(&DeviceExtension
->LunExtensionListHead
))
438 Entry
= DeviceExtension
->LunExtensionListHead
.Flink
;
439 while (Entry
!= &DeviceExtension
->LunExtensionListHead
)
441 LunExtension
= CONTAINING_RECORD(Entry
,
442 SCSI_PORT_LUN_EXTENSION
,
444 if (LunExtension
->PathId
== PathId
&&
445 LunExtension
->TargetId
== TargetId
&&
446 LunExtension
->Lun
== Lun
)
448 return (PVOID
)&LunExtension
->MiniportLunExtension
;
451 Entry
= Entry
->Flink
;
461 SCSI_PHYSICAL_ADDRESS STDCALL
462 ScsiPortGetPhysicalAddress(IN PVOID HwDeviceExtension
,
463 IN PSCSI_REQUEST_BLOCK Srb OPTIONAL
,
464 IN PVOID VirtualAddress
,
467 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
468 SCSI_PHYSICAL_ADDRESS PhysicalAddress
;
469 SCSI_PHYSICAL_ADDRESS NextPhysicalAddress
;
470 ULONG BufferLength
= 0;
474 DPRINT("ScsiPortGetPhysicalAddress(%p %p %p %p)\n",
475 HwDeviceExtension
, Srb
, VirtualAddress
, Length
);
477 DeviceExtension
= CONTAINING_RECORD(HwDeviceExtension
,
478 SCSI_PORT_DEVICE_EXTENSION
,
479 MiniPortDeviceExtension
);
487 EndAddress
= (PVOID
)((ULONG_PTR
)DeviceExtension
->VirtualAddress
+ DeviceExtension
->CommonBufferLength
);
488 if (VirtualAddress
>= DeviceExtension
->VirtualAddress
&& VirtualAddress
< EndAddress
)
490 Offset
= (ULONG_PTR
)VirtualAddress
- (ULONG_PTR
)DeviceExtension
->VirtualAddress
;
491 PhysicalAddress
.QuadPart
= DeviceExtension
->PhysicalAddress
.QuadPart
+ Offset
;
492 BufferLength
= (ULONG_PTR
)EndAddress
- (ULONG_PTR
)VirtualAddress
;
497 * The given virtual address is not within the range
498 * of the drivers uncached extension or srb extension.
502 * Check if the address is a sense info buffer of an active srb.
504 PhysicalAddress
= MmGetPhysicalAddress(VirtualAddress
);
505 if (PhysicalAddress
.QuadPart
== 0LL)
508 return PhysicalAddress
;
510 BufferLength
= PAGE_SIZE
- PhysicalAddress
.u
.LowPart
% PAGE_SIZE
;
515 EndAddress
= (PVOID
)((ULONG_PTR
)Srb
->DataBuffer
+ Srb
->DataTransferLength
);
516 if (VirtualAddress
== NULL
)
518 VirtualAddress
= Srb
->DataBuffer
;
520 else if (VirtualAddress
< Srb
->DataBuffer
|| VirtualAddress
>= EndAddress
)
522 EndAddress
= (PVOID
)((ULONG_PTR
)Srb
->SenseInfoBuffer
+ Srb
->SenseInfoBufferLength
);
523 if (VirtualAddress
< Srb
->SenseInfoBuffer
|| VirtualAddress
>= EndAddress
)
525 PhysicalAddress
.QuadPart
= 0LL;
527 return PhysicalAddress
;
531 PhysicalAddress
= MmGetPhysicalAddress(VirtualAddress
);
532 if (PhysicalAddress
.QuadPart
== 0LL)
535 return PhysicalAddress
;
538 BufferLength
= PAGE_SIZE
- (ULONG_PTR
)VirtualAddress
% PAGE_SIZE
;
539 while ((ULONG_PTR
)VirtualAddress
+ BufferLength
< (ULONG_PTR
)EndAddress
)
541 NextPhysicalAddress
= MmGetPhysicalAddress((PVOID
)((ULONG_PTR
)VirtualAddress
+ BufferLength
));
542 if (PhysicalAddress
.QuadPart
+ BufferLength
!= NextPhysicalAddress
.QuadPart
)
546 BufferLength
+= PAGE_SIZE
;
548 if ((ULONG_PTR
)VirtualAddress
+ BufferLength
>= (ULONG_PTR
)EndAddress
)
550 BufferLength
= (ULONG
)((ULONG_PTR
)EndAddress
- (ULONG_PTR
)VirtualAddress
);
555 *Length
= BufferLength
;
557 DPRINT("Address %I64x, Length %d\n", PhysicalAddress
.QuadPart
, BufferLength
);
558 return PhysicalAddress
;
565 PSCSI_REQUEST_BLOCK STDCALL
566 ScsiPortGetSrb(IN PVOID HwDeviceExtension
,
572 DPRINT1("ScsiPortGetSrb() unimplemented\n");
582 ScsiPortGetUncachedExtension(IN PVOID HwDeviceExtension
,
583 IN PPORT_CONFIGURATION_INFORMATION ConfigInfo
,
584 IN ULONG NumberOfBytes
)
586 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
587 DEVICE_DESCRIPTION DeviceDescription
;
589 DPRINT("ScsiPortGetUncachedExtension(%p %p %lu)\n",
590 HwDeviceExtension
, ConfigInfo
, NumberOfBytes
);
592 DeviceExtension
= CONTAINING_RECORD(HwDeviceExtension
,
593 SCSI_PORT_DEVICE_EXTENSION
,
594 MiniPortDeviceExtension
);
596 /* Check for allocated common DMA buffer */
597 if (DeviceExtension
->VirtualAddress
!= NULL
)
599 DPRINT1("The HBA has already got a common DMA buffer!\n");
603 /* Check for DMA adapter object */
604 if (DeviceExtension
->AdapterObject
== NULL
)
606 /* Initialize DMA adapter description */
607 RtlZeroMemory(&DeviceDescription
,
608 sizeof(DEVICE_DESCRIPTION
));
609 DeviceDescription
.Version
= DEVICE_DESCRIPTION_VERSION
;
610 DeviceDescription
.Master
= ConfigInfo
->Master
;
611 DeviceDescription
.ScatterGather
= ConfigInfo
->ScatterGather
;
612 DeviceDescription
.DemandMode
= ConfigInfo
->DemandMode
;
613 DeviceDescription
.Dma32BitAddresses
= ConfigInfo
->Dma32BitAddresses
;
614 DeviceDescription
.BusNumber
= ConfigInfo
->SystemIoBusNumber
;
615 DeviceDescription
.DmaChannel
= ConfigInfo
->DmaChannel
;
616 DeviceDescription
.InterfaceType
= ConfigInfo
->AdapterInterfaceType
;
617 DeviceDescription
.DmaWidth
= ConfigInfo
->DmaWidth
;
618 DeviceDescription
.DmaSpeed
= ConfigInfo
->DmaSpeed
;
619 DeviceDescription
.MaximumLength
= ConfigInfo
->MaximumTransferLength
;
620 DeviceDescription
.DmaPort
= ConfigInfo
->DmaPort
;
622 /* Get a DMA adapter object */
623 DeviceExtension
->AdapterObject
= HalGetAdapter(&DeviceDescription
,
624 &DeviceExtension
->MapRegisterCount
);
625 if (DeviceExtension
->AdapterObject
== NULL
)
627 DPRINT1("HalGetAdapter() failed\n");
631 if (DeviceExtension
->SrbExtensionSize
> 0)
634 DeviceExtension
->CurrentSrbExtensions
= 0;
635 if (DeviceExtension
->PortConfig
->MultipleRequestPerLu
)
637 DeviceExtension
->MaxSrbExtensions
= 1024;
641 DeviceExtension
->MaxSrbExtensions
= 32;
643 Buffer
= ExAllocatePool(NonPagedPool
, ROUND_UP(DeviceExtension
->MaxSrbExtensions
/ 8, sizeof(ULONG
)));
649 RtlInitializeBitMap(&DeviceExtension
->SrbExtensionAllocMap
, Buffer
, DeviceExtension
->MaxSrbExtensions
);
650 RtlClearAllBits(&DeviceExtension
->SrbExtensionAllocMap
);
653 /* Allocate a common DMA buffer */
654 DeviceExtension
->CommonBufferLength
=
655 NumberOfBytes
+ PAGE_ROUND_UP(DeviceExtension
->SrbExtensionSize
* DeviceExtension
->MaxSrbExtensions
);
656 DeviceExtension
->VirtualAddress
=
657 HalAllocateCommonBuffer(DeviceExtension
->AdapterObject
,
658 DeviceExtension
->CommonBufferLength
,
659 &DeviceExtension
->PhysicalAddress
,
661 if (DeviceExtension
->VirtualAddress
== NULL
)
663 DPRINT1("HalAllocateCommonBuffer() failed!\n");
664 DeviceExtension
->CommonBufferLength
= 0;
668 return (PVOID
)((ULONG_PTR
)DeviceExtension
->VirtualAddress
+
669 PAGE_ROUND_UP(DeviceExtension
->SrbExtensionSize
* DeviceExtension
->MaxSrbExtensions
));
677 ScsiPortGetVirtualAddress(IN PVOID HwDeviceExtension
,
678 IN SCSI_PHYSICAL_ADDRESS PhysicalAddress
)
680 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
683 DPRINT("ScsiPortGetVirtualAddress(%p %I64x)\n",
684 HwDeviceExtension
, PhysicalAddress
.QuadPart
);
686 DeviceExtension
= CONTAINING_RECORD(HwDeviceExtension
,
687 SCSI_PORT_DEVICE_EXTENSION
,
688 MiniPortDeviceExtension
);
690 if (DeviceExtension
->PhysicalAddress
.QuadPart
> PhysicalAddress
.QuadPart
)
693 Offset
= (ULONG
)(PhysicalAddress
.QuadPart
- DeviceExtension
->PhysicalAddress
.QuadPart
);
694 if (Offset
>= DeviceExtension
->CommonBufferLength
)
697 return (PVOID
)((ULONG_PTR
)DeviceExtension
->VirtualAddress
+ Offset
);
701 /**********************************************************************
706 * Initializes SCSI port driver specific data.
713 * Pointer to the miniport driver's driver object.
716 * Pointer to the miniport driver's registry path.
718 * HwInitializationData
719 * Pointer to port driver specific configuration data.
722 Miniport driver specific context.
731 ScsiPortInitialize(IN PVOID Argument1
,
733 IN
struct _HW_INITIALIZATION_DATA
*HwInitializationData
,
736 PDRIVER_OBJECT DriverObject
= (PDRIVER_OBJECT
)Argument1
;
737 // PUNICODE_STRING RegistryPath = (PUNICODE_STRING)Argument2;
738 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
739 PCONFIGURATION_INFORMATION SystemConfig
;
740 PPORT_CONFIGURATION_INFORMATION PortConfig
;
741 ULONG DeviceExtensionSize
;
742 ULONG PortConfigSize
;
744 BOOLEAN DeviceFound
= FALSE
;
750 PCI_SLOT_NUMBER SlotNumber
;
752 PDEVICE_OBJECT PortDeviceObject
;
753 WCHAR NameBuffer
[80];
754 UNICODE_STRING DeviceName
;
755 WCHAR DosNameBuffer
[80];
756 UNICODE_STRING DosDeviceName
;
757 PIO_SCSI_CAPABILITIES PortCapabilities
;
763 DPRINT ("ScsiPortInitialize() called!\n");
765 DPRINT1("HwInitializationDataSize: %d\n", HwInitializationData
->HwInitializationDataSize
);
766 DPRINT1("AdapterInterfaceType: %d\n", HwInitializationData
->AdapterInterfaceType
);
767 DPRINT1("HwInitialize: %x\n", HwInitializationData
->HwInitialize
);
768 DPRINT1("HwStartIo: %x\n", HwInitializationData
->HwStartIo
);
769 DPRINT1("HwInterrupt: %x\n", HwInitializationData
->HwInterrupt
);
770 DPRINT1("HwFindAdapter: %x\n", HwInitializationData
->HwFindAdapter
);
771 DPRINT1("HwResetBus: %x\n", HwInitializationData
->HwResetBus
);
772 DPRINT1("HwDmaStarted: %x\n", HwInitializationData
->HwDmaStarted
);
773 DPRINT1("HwAdapterState: %x\n", HwInitializationData
->HwAdapterState
);
774 DPRINT1("DeviceExtensionSize: %d\n", HwInitializationData
->DeviceExtensionSize
);
775 DPRINT1("SpecificLuExtensionSize: %d\n", HwInitializationData
->SpecificLuExtensionSize
);
776 DPRINT1("SrbExtensionSize: %d\n", HwInitializationData
->SrbExtensionSize
);
777 DPRINT1("NumberOfAccessRanges: %d\n", HwInitializationData
->NumberOfAccessRanges
);
778 DPRINT1("Reserved: %x\n", HwInitializationData
->Reserved
);
779 DPRINT1("MapBuffers: %d\n", HwInitializationData
->MapBuffers
);
780 DPRINT1("NeedPhysicalAddresses: %d\n", HwInitializationData
->NeedPhysicalAddresses
);
781 DPRINT1("TaggedQueueing: %d\n", HwInitializationData
->TaggedQueueing
);
782 DPRINT1("AutoRequestSense: %d\n", HwInitializationData
->AutoRequestSense
);
783 DPRINT1("MultipleRequestPerLu: %d\n", HwInitializationData
->MultipleRequestPerLu
);
784 DPRINT1("ReceiveEvent: %d\n", HwInitializationData
->ReceiveEvent
);
785 DPRINT1("VendorIdLength: %d\n", HwInitializationData
->VendorIdLength
);
786 DPRINT1("VendorId: %x\n", HwInitializationData
->VendorId
);
787 DPRINT1("ReservedUshort: %d\n", HwInitializationData
->ReservedUshort
);
788 DPRINT1("DeviceIdLength: %d\n", HwInitializationData
->DeviceIdLength
);
789 DPRINT1("DeviceId: %x\n", HwInitializationData
->DeviceId
);
791 if ((HwInitializationData
->HwInitialize
== NULL
) ||
792 (HwInitializationData
->HwStartIo
== NULL
) ||
793 (HwInitializationData
->HwInterrupt
== NULL
) ||
794 (HwInitializationData
->HwFindAdapter
== NULL
) ||
795 (HwInitializationData
->HwResetBus
== NULL
))
796 return(STATUS_INVALID_PARAMETER
);
798 DriverObject
->DriverStartIo
= NULL
;
799 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = ScsiPortCreateClose
;
800 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = ScsiPortCreateClose
;
801 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = ScsiPortDeviceControl
;
802 DriverObject
->MajorFunction
[IRP_MJ_SCSI
] = ScsiPortDispatchScsi
;
804 SystemConfig
= IoGetConfigurationInformation();
806 DeviceExtensionSize
= sizeof(SCSI_PORT_DEVICE_EXTENSION
) +
807 HwInitializationData
->DeviceExtensionSize
;
808 PortConfigSize
= sizeof(PORT_CONFIGURATION_INFORMATION
) +
809 HwInitializationData
->NumberOfAccessRanges
* sizeof(ACCESS_RANGE
);
812 MaxBus
= (HwInitializationData
->AdapterInterfaceType
== PCIBus
) ? 8 : 1;
813 DPRINT("MaxBus: %lu\n", MaxBus
);
815 PortDeviceObject
= NULL
;
817 SlotNumber
.u
.AsULONG
= 0;
820 /* Create a unicode device name */
821 swprintf (NameBuffer
,
822 L
"\\Device\\ScsiPort%lu",
823 SystemConfig
->ScsiPortCount
);
824 RtlInitUnicodeString (&DeviceName
,
827 DPRINT("Creating device: %wZ\n", &DeviceName
);
829 /* Create the port device */
830 Status
= IoCreateDevice (DriverObject
,
833 FILE_DEVICE_CONTROLLER
,
837 if (!NT_SUCCESS(Status
))
839 DbgPrint ("IoCreateDevice call failed! (Status 0x%lX)\n", Status
);
840 PortDeviceObject
= NULL
;
844 DPRINT ("Created device: %wZ (%p)\n", &DeviceName
, PortDeviceObject
);
846 /* Increase the stacksize. We reenter our device on IOCTL_SCSI_MINIPORT */
847 PortDeviceObject
->StackSize
++;
849 /* Set the buffering strategy here... */
850 PortDeviceObject
->Flags
|= DO_DIRECT_IO
;
851 PortDeviceObject
->AlignmentRequirement
= FILE_WORD_ALIGNMENT
;
853 DeviceExtension
= PortDeviceObject
->DeviceExtension
;
854 RtlZeroMemory(DeviceExtension
, DeviceExtensionSize
);
855 DeviceExtension
->Length
= DeviceExtensionSize
;
856 DeviceExtension
->DeviceObject
= PortDeviceObject
;
857 DeviceExtension
->PortNumber
= SystemConfig
->ScsiPortCount
;
859 DeviceExtension
->MiniPortExtensionSize
= HwInitializationData
->DeviceExtensionSize
;
860 DeviceExtension
->LunExtensionSize
= HwInitializationData
->SpecificLuExtensionSize
;
861 DeviceExtension
->SrbExtensionSize
= HwInitializationData
->SrbExtensionSize
;
862 DeviceExtension
->HwStartIo
= HwInitializationData
->HwStartIo
;
863 DeviceExtension
->HwInterrupt
= HwInitializationData
->HwInterrupt
;
865 DeviceExtension
->AdapterObject
= NULL
;
866 DeviceExtension
->MapRegisterCount
= 0;
867 DeviceExtension
->PhysicalAddress
.QuadPart
= 0ULL;
868 DeviceExtension
->VirtualAddress
= NULL
;
869 DeviceExtension
->CommonBufferLength
= 0;
871 /* Initialize the device base list */
872 InitializeListHead (&DeviceExtension
->DeviceBaseListHead
);
874 /* Initialize the irp lists */
875 InitializeListHead (&DeviceExtension
->PendingIrpListHead
);
876 DeviceExtension
->NextIrp
= NULL
;
877 DeviceExtension
->PendingIrpCount
= 0;
878 DeviceExtension
->ActiveIrpCount
= 0;
880 /* Initialize LUN-Extension list */
881 InitializeListHead (&DeviceExtension
->LunExtensionListHead
);
883 /* Initialize the spin lock in the controller extension */
884 KeInitializeSpinLock (&DeviceExtension
->Lock
);
886 /* Initialize the DPC object */
887 IoInitializeDpcRequest (PortDeviceObject
,
890 /* Initialize the device timer */
891 DeviceExtension
->TimerState
= IDETimerIdle
;
892 DeviceExtension
->TimerCount
= 0;
893 IoInitializeTimer (PortDeviceObject
,
897 /* Allocate and initialize port configuration info */
898 DeviceExtension
->PortConfig
= ExAllocatePool (NonPagedPool
,
900 if (DeviceExtension
->PortConfig
== NULL
)
902 Status
= STATUS_INSUFFICIENT_RESOURCES
;
905 RtlZeroMemory (DeviceExtension
->PortConfig
,
908 PortConfig
= DeviceExtension
->PortConfig
;
909 PortConfig
->Length
= sizeof(PORT_CONFIGURATION_INFORMATION
);
910 PortConfig
->SystemIoBusNumber
= BusNumber
;
911 PortConfig
->AdapterInterfaceType
= HwInitializationData
->AdapterInterfaceType
;
912 PortConfig
->InterruptMode
=
913 (PortConfig
->AdapterInterfaceType
== PCIBus
) ? LevelSensitive
: Latched
;
914 PortConfig
->MaximumTransferLength
= SP_UNINITIALIZED_VALUE
;
915 PortConfig
->NumberOfPhysicalBreaks
= SP_UNINITIALIZED_VALUE
;
916 PortConfig
->DmaChannel
= SP_UNINITIALIZED_VALUE
;
917 PortConfig
->DmaPort
= SP_UNINITIALIZED_VALUE
;
918 PortConfig
->DmaWidth
= 0;
919 PortConfig
->DmaSpeed
= Compatible
;
920 PortConfig
->AlignmentMask
= 0;
921 PortConfig
->NumberOfAccessRanges
= HwInitializationData
->NumberOfAccessRanges
;
922 PortConfig
->NumberOfBuses
= 0;
924 for (i
= 0; i
< SCSI_MAXIMUM_BUSES
; i
++)
925 PortConfig
->InitiatorBusId
[i
] = 255;
927 PortConfig
->ScatterGather
= FALSE
;
928 PortConfig
->Master
= FALSE
;
929 PortConfig
->CachesData
= FALSE
;
930 PortConfig
->AdapterScansDown
= FALSE
;
931 PortConfig
->AtdiskPrimaryClaimed
= SystemConfig
->AtDiskPrimaryAddressClaimed
;
932 PortConfig
->AtdiskSecondaryClaimed
= SystemConfig
->AtDiskSecondaryAddressClaimed
;
933 PortConfig
->Dma32BitAddresses
= FALSE
;
934 PortConfig
->DemandMode
= FALSE
;
935 PortConfig
->MapBuffers
= HwInitializationData
->MapBuffers
;
936 PortConfig
->NeedPhysicalAddresses
= HwInitializationData
->NeedPhysicalAddresses
;
937 PortConfig
->TaggedQueuing
= HwInitializationData
->TaggedQueuing
;
938 PortConfig
->AutoRequestSense
= HwInitializationData
->AutoRequestSense
;
939 PortConfig
->MultipleRequestPerLu
= HwInitializationData
->MultipleRequestPerLu
;
940 PortConfig
->ReceiveEvent
= HwInitializationData
->ReceiveEvent
;
941 PortConfig
->RealModeInitialized
= FALSE
;
942 PortConfig
->BufferAccessScsiPortControlled
= FALSE
;
943 PortConfig
->MaximumNumberOfTargets
= SCSI_MAXIMUM_TARGETS
;
944 // PortConfig->MaximumNumberOfLogicalUnits = SCSI_MAXIMUM_LOGICAL_UNITS;
946 PortConfig
->SrbExtensionSize
= HwInitializationData
->SrbExtensionSize
;
947 PortConfig
->SpecificLuExtensionSize
= HwInitializationData
->SpecificLuExtensionSize
;
949 PortConfig
->AccessRanges
= (ACCESS_RANGE(*)[])(PortConfig
+ 1);
951 /* Search for matching PCI device */
952 if ((HwInitializationData
->AdapterInterfaceType
== PCIBus
) &&
953 (HwInitializationData
->VendorIdLength
> 0) &&
954 (HwInitializationData
->VendorId
!= NULL
) &&
955 (HwInitializationData
->DeviceIdLength
> 0) &&
956 (HwInitializationData
->DeviceId
!= NULL
))
958 /* Get PCI device data */
959 DPRINT("VendorId '%.*s' DeviceId '%.*s'\n",
960 HwInitializationData
->VendorIdLength
,
961 HwInitializationData
->VendorId
,
962 HwInitializationData
->DeviceIdLength
,
963 HwInitializationData
->DeviceId
);
965 if (!SpiGetPciConfigData (HwInitializationData
,
970 Status
= STATUS_UNSUCCESSFUL
;
975 /* Note: HwFindAdapter is called once for each bus */
977 DPRINT("Calling HwFindAdapter() for Bus %lu\n", PortConfig
->SystemIoBusNumber
);
978 Result
= (HwInitializationData
->HwFindAdapter
)(&DeviceExtension
->MiniPortDeviceExtension
,
980 0, /* BusInformation */
981 "", /* ArgumentString */
984 DPRINT("HwFindAdapter() Result: %lu Again: %s\n",
985 Result
, (Again
) ? "True" : "False");
987 if (Result
== SP_RETURN_FOUND
)
989 DPRINT("ScsiPortInitialize(): Found HBA! (%x)\n", PortConfig
->BusInterruptVector
);
992 DPRINT1("SystemIoBusNumber: %x\n", PortConfig
->SystemIoBusNumber
);
993 DPRINT1("AdapterInterfaceType: %x\n", PortConfig
->AdapterInterfaceType
);
994 DPRINT1("BusInterruptLevel: %x\n", PortConfig
->BusInterruptLevel
);
995 DPRINT1("BusInterruptVector: %x\n", PortConfig
->BusInterruptVector
);
996 DPRINT1("InterruptMode: %x\n", PortConfig
->InterruptMode
);
997 DPRINT1("MaximumTransferLength: %x\n", PortConfig
->MaximumTransferLength
);
998 DPRINT1("NumberOfPhysicalBreaks: %x\n", PortConfig
->NumberOfPhysicalBreaks
);
999 DPRINT1("DmaChannel: %x\n", PortConfig
->DmaChannel
);
1000 DPRINT1("DmaPort: %d\n", PortConfig
->DmaPort
);
1001 DPRINT1("DmaWidth: %d\n", PortConfig
->DmaWidth
);
1002 DPRINT1("DmaSpeed: %d\n", PortConfig
->DmaSpeed
);
1003 DPRINT1("AlignmentMask: %d\n", PortConfig
->AlignmentMask
);
1004 DPRINT1("NumberOfAccessRanges: %d\n", PortConfig
->NumberOfAccessRanges
);
1005 DPRINT1("NumberOfBuses: %d\n", PortConfig
->NumberOfBuses
);
1006 DPRINT1("ScatterGather: %d\n", PortConfig
->ScatterGather
);
1007 DPRINT1("Master: %d\n", PortConfig
->Master
);
1008 DPRINT1("CachesData: %d\n", PortConfig
->CachesData
);
1009 DPRINT1("AdapterScansDown: %d\n", PortConfig
->AdapterScansDown
);
1010 DPRINT1("AtdiskPrimaryClaimed: %d\n", PortConfig
->AtdiskPrimaryClaimed
);
1011 DPRINT1("AtdiskSecondaryClaimed: %d\n", PortConfig
->AtdiskSecondaryClaimed
);
1012 DPRINT1("Dma32BitAddresses: %d\n", PortConfig
->Dma32BitAddresses
);
1013 DPRINT1("DemandMode: %d\n", PortConfig
->DemandMode
);
1014 DPRINT1("MapBuffers: %d\n", PortConfig
->MapBuffers
);
1015 DPRINT1("NeedPhysicalAddresses: %d\n", PortConfig
->NeedPhysicalAddresses
);
1016 DPRINT1("TaggedQueuing: %d\n", PortConfig
->TaggedQueuing
);
1017 DPRINT1("AutoRequestSense: %d\n", PortConfig
->AutoRequestSense
);
1018 DPRINT1("MultipleRequestPerLu: %d\n", PortConfig
->MultipleRequestPerLu
);
1019 DPRINT1("ReceiveEvent: %d\n", PortConfig
->ReceiveEvent
);
1020 DPRINT1("RealModeInitialized: %d\n", PortConfig
->RealModeInitialized
);
1021 DPRINT1("BufferAccessScsiPortControlled: %d\n", PortConfig
->BufferAccessScsiPortControlled
);
1022 DPRINT1("MaximumNumberOfTargets: %d\n", PortConfig
->MaximumNumberOfTargets
);
1023 DPRINT1("SlotNumber: %d\n", PortConfig
->SlotNumber
);
1024 DPRINT1("BusInterruptLevel2: %x\n", PortConfig
->BusInterruptLevel2
);
1025 DPRINT1("BusInterruptVector2: %x\n", PortConfig
->BusInterruptVector2
);
1026 DPRINT1("InterruptMode2: %x\n", PortConfig
->InterruptMode2
);
1027 DPRINT1("DmaChannel2: %d\n", PortConfig
->DmaChannel2
);
1028 DPRINT1("DmaPort2: %d\n", PortConfig
->DmaPort2
);
1029 DPRINT1("DmaWidth2: %d\n", PortConfig
->DmaWidth2
);
1030 DPRINT1("DmaSpeed2: %d\n", PortConfig
->DmaSpeed2
);
1031 DPRINT1("DeviceExtensionSize: %d\n", PortConfig
->DeviceExtensionSize
);
1032 DPRINT1("SpecificLuExtensionSize: %d\n", PortConfig
->SpecificLuExtensionSize
);
1033 DPRINT1("SrbExtensionSize: %d\n", PortConfig
->SrbExtensionSize
);
1037 if (DeviceExtension
->VirtualAddress
== NULL
&& DeviceExtension
->SrbExtensionSize
)
1039 ScsiPortGetUncachedExtension(&DeviceExtension
->MiniPortDeviceExtension
,
1044 /* Register an interrupt handler for this device */
1045 MappedIrq
= HalGetInterruptVector(PortConfig
->AdapterInterfaceType
,
1046 PortConfig
->SystemIoBusNumber
,
1047 PortConfig
->BusInterruptLevel
,
1051 * Something is wrong in our interrupt conecting code.
1052 * The promise Ultra100TX driver returns 0 for BusInterruptVector
1053 * and a nonzero value for BusInterruptLevel. The driver does only
1054 * work with this fix.
1056 PortConfig
->BusInterruptLevel
,
1058 PortConfig
->BusInterruptVector
,
1062 DPRINT("AdapterInterfaceType %x, SystemIoBusNumber %x, BusInterruptLevel %x, BusInterruptVector %x\n",
1063 PortConfig
->AdapterInterfaceType
, PortConfig
->SystemIoBusNumber
,
1064 PortConfig
->BusInterruptLevel
, PortConfig
->BusInterruptVector
);
1065 Status
= IoConnectInterrupt(&DeviceExtension
->Interrupt
,
1072 PortConfig
->InterruptMode
,
1076 if (!NT_SUCCESS(Status
))
1078 DbgPrint("Could not connect interrupt %d\n",
1079 PortConfig
->BusInterruptVector
);
1083 if (!(HwInitializationData
->HwInitialize
)(&DeviceExtension
->MiniPortDeviceExtension
))
1085 DbgPrint("HwInitialize() failed!");
1086 Status
= STATUS_UNSUCCESSFUL
;
1090 /* Initialize port capabilities */
1091 DeviceExtension
->PortCapabilities
= ExAllocatePool(NonPagedPool
,
1092 sizeof(IO_SCSI_CAPABILITIES
));
1093 if (DeviceExtension
->PortCapabilities
== NULL
)
1095 DbgPrint("Failed to allocate port capabilities!\n");
1096 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1100 PortCapabilities
= DeviceExtension
->PortCapabilities
;
1101 PortCapabilities
->Length
= sizeof(IO_SCSI_CAPABILITIES
);
1102 if (PortConfig
->ScatterGather
== FALSE
||
1103 PortConfig
->NumberOfPhysicalBreaks
>= (0x100000000LL
>> PAGE_SHIFT
) ||
1104 PortConfig
->MaximumTransferLength
< PortConfig
->NumberOfPhysicalBreaks
* PAGE_SIZE
)
1106 PortCapabilities
->MaximumTransferLength
=
1107 PortConfig
->MaximumTransferLength
;
1111 PortCapabilities
->MaximumTransferLength
=
1112 PortConfig
->NumberOfPhysicalBreaks
* PAGE_SIZE
;
1115 PortCapabilities
->MaximumPhysicalPages
=
1116 PortCapabilities
->MaximumTransferLength
/ PAGE_SIZE
;
1117 PortCapabilities
->SupportedAsynchronousEvents
= 0; /* FIXME */
1118 PortCapabilities
->AlignmentMask
=
1119 PortConfig
->AlignmentMask
;
1120 PortCapabilities
->TaggedQueuing
=
1121 PortConfig
->TaggedQueuing
;
1122 PortCapabilities
->AdapterScansDown
=
1123 PortConfig
->AdapterScansDown
;
1124 PortCapabilities
->AdapterUsesPio
= TRUE
; /* FIXME */
1126 /* Scan the adapter for devices */
1127 SpiScanAdapter (DeviceExtension
);
1129 /* Build the registry device map */
1130 SpiBuildDeviceMap (DeviceExtension
,
1131 (PUNICODE_STRING
)Argument2
);
1133 /* Create the dos device link */
1134 swprintf(DosNameBuffer
,
1136 SystemConfig
->ScsiPortCount
);
1137 RtlInitUnicodeString(&DosDeviceName
,
1139 IoCreateSymbolicLink(&DosDeviceName
,
1142 /* Update the system configuration info */
1143 if (PortConfig
->AtdiskPrimaryClaimed
== TRUE
)
1144 SystemConfig
->AtDiskPrimaryAddressClaimed
= TRUE
;
1145 if (PortConfig
->AtdiskSecondaryClaimed
== TRUE
)
1146 SystemConfig
->AtDiskSecondaryAddressClaimed
= TRUE
;
1148 SystemConfig
->ScsiPortCount
++;
1149 PortDeviceObject
= NULL
;
1154 DPRINT("HwFindAdapter() Result: %lu\n", Result
);
1156 ExFreePool (PortConfig
);
1157 IoDeleteDevice (PortDeviceObject
);
1158 PortDeviceObject
= NULL
;
1161 DPRINT("Bus: %lu MaxBus: %lu\n", BusNumber
, MaxBus
);
1162 if (BusNumber
>= MaxBus
)
1164 DPRINT("Scanned all buses!\n");
1165 Status
= STATUS_SUCCESS
;
1172 SlotNumber
.u
.AsULONG
= 0;
1177 /* Clean up the mess */
1178 if (PortDeviceObject
!= NULL
)
1180 DPRINT("Delete device: %p\n", PortDeviceObject
);
1182 DeviceExtension
= PortDeviceObject
->DeviceExtension
;
1184 if (DeviceExtension
->PortCapabilities
!= NULL
)
1186 IoDisconnectInterrupt (DeviceExtension
->Interrupt
);
1187 ExFreePool (DeviceExtension
->PortCapabilities
);
1190 if (DeviceExtension
->PortConfig
!= NULL
)
1192 ExFreePool (DeviceExtension
->PortConfig
);
1195 IoDeleteDevice (PortDeviceObject
);
1198 DPRINT("ScsiPortInitialize() done!\n");
1200 return (DeviceFound
== FALSE
) ? Status
: STATUS_SUCCESS
;
1208 ScsiPortIoMapTransfer(IN PVOID HwDeviceExtension
,
1209 IN PSCSI_REQUEST_BLOCK Srb
,
1210 IN ULONG LogicalAddress
,
1213 DPRINT1("ScsiPortIoMapTransfer()\n");
1222 ScsiPortLogError(IN PVOID HwDeviceExtension
,
1223 IN PSCSI_REQUEST_BLOCK Srb OPTIONAL
,
1230 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
1232 DPRINT1("ScsiPortLogError() called\n");
1233 DPRINT1("Srb %x, PathId %d, TargetId %d, Lun %d, ErrorCode %x, UniqueId %x\n",
1234 Srb
, PathId
, TargetId
, Lun
, ErrorCode
, UniqueId
);
1236 DeviceExtension
= CONTAINING_RECORD(HwDeviceExtension
,
1237 SCSI_PORT_DEVICE_EXTENSION
,
1238 MiniPortDeviceExtension
);
1241 DPRINT("ScsiPortLogError() done\n");
1249 ScsiPortMoveMemory(OUT PVOID Destination
,
1253 RtlMoveMemory(Destination
,
1263 ScsiPortNotification(IN SCSI_NOTIFICATION_TYPE NotificationType
,
1264 IN PVOID HwDeviceExtension
,
1267 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
1270 DPRINT("ScsiPortNotification() called\n");
1272 DeviceExtension
= CONTAINING_RECORD(HwDeviceExtension
,
1273 SCSI_PORT_DEVICE_EXTENSION
,
1274 MiniPortDeviceExtension
);
1276 DPRINT("DeviceExtension %p\n", DeviceExtension
);
1278 va_start(ap
, HwDeviceExtension
);
1280 switch (NotificationType
)
1282 case RequestComplete
:
1284 PSCSI_REQUEST_BLOCK Srb
;
1286 Srb
= (PSCSI_REQUEST_BLOCK
) va_arg (ap
, PSCSI_REQUEST_BLOCK
);
1288 DPRINT("Notify: RequestComplete (Srb %p)\n", Srb
);
1289 DeviceExtension
->Flags
|= IRP_FLAG_COMPLETE
;
1290 Srb
->SrbFlags
&= ~SRB_FLAGS_IS_ACTIVE
;
1295 DPRINT("Notify: NextRequest\n");
1296 DeviceExtension
->Flags
|= IRP_FLAG_NEXT
;
1304 PSCSI_PORT_LUN_EXTENSION LunExtension
;
1306 PathId
= (UCHAR
) va_arg (ap
, int);
1307 TargetId
= (UCHAR
) va_arg (ap
, int);
1308 Lun
= (UCHAR
) va_arg (ap
, int);
1310 DPRINT ("Notify: NextLuRequest(PathId %u TargetId %u Lun %u)\n",
1311 PathId
, TargetId
, Lun
);
1313 LunExtension
= SpiGetLunExtension(DeviceExtension
,
1319 DeviceExtension
->Flags
|= IRP_FLAG_NEXT_LU
;
1320 LunExtension
->Flags
|= IRP_FLAG_NEXT_LU
;
1326 DPRINT1("Notify: ResetDetected\n");
1331 DPRINT1 ("Unsupported notification %lu\n", NotificationType
);
1334 if (KeGetCurrentIrql() >= DISPATCH_LEVEL
)
1336 IoRequestDpc(DeviceExtension
->DeviceObject
,
1342 SpiProcessRequests(DeviceExtension
, NULL
);
1353 ScsiPortSetBusDataByOffset(IN PVOID DeviceExtension
,
1354 IN ULONG BusDataType
,
1355 IN ULONG SystemIoBusNumber
,
1356 IN ULONG SlotNumber
,
1361 DPRINT("ScsiPortSetBusDataByOffset()\n");
1362 return(HalSetBusDataByOffset(BusDataType
,
1375 ScsiPortValidateRange(IN PVOID HwDeviceExtension
,
1376 IN INTERFACE_TYPE BusType
,
1377 IN ULONG SystemIoBusNumber
,
1378 IN SCSI_PHYSICAL_ADDRESS IoAddress
,
1379 IN ULONG NumberOfBytes
,
1380 IN BOOLEAN InIoSpace
)
1382 DPRINT("ScsiPortValidateRange()\n");
1387 /* INTERNAL FUNCTIONS ********************************************************/
1391 SpiGetPciConfigData (IN
struct _HW_INITIALIZATION_DATA
*HwInitializationData
,
1392 IN OUT PPORT_CONFIGURATION_INFORMATION PortConfig
,
1394 IN OUT PPCI_SLOT_NUMBER NextSlotNumber
)
1396 PCI_COMMON_CONFIG PciConfig
;
1397 PCI_SLOT_NUMBER SlotNumber
;
1400 ULONG FunctionNumber
;
1401 CHAR VendorIdString
[8];
1402 CHAR DeviceIdString
[8];
1406 DPRINT ("SpiGetPciConfiguration() called\n");
1408 if (NextSlotNumber
->u
.bits
.FunctionNumber
>= PCI_MAX_FUNCTION
)
1410 NextSlotNumber
->u
.bits
.FunctionNumber
= 0;
1411 NextSlotNumber
->u
.bits
.DeviceNumber
++;
1414 if (NextSlotNumber
->u
.bits
.DeviceNumber
>= PCI_MAX_DEVICES
)
1416 NextSlotNumber
->u
.bits
.DeviceNumber
= 0;
1420 for (DeviceNumber
= NextSlotNumber
->u
.bits
.DeviceNumber
; DeviceNumber
< PCI_MAX_DEVICES
; DeviceNumber
++)
1422 SlotNumber
.u
.bits
.DeviceNumber
= DeviceNumber
;
1424 for (FunctionNumber
= NextSlotNumber
->u
.bits
.FunctionNumber
; FunctionNumber
< PCI_MAX_FUNCTION
; FunctionNumber
++)
1426 SlotNumber
.u
.bits
.FunctionNumber
= FunctionNumber
;
1428 DataSize
= HalGetBusData (PCIConfiguration
,
1430 SlotNumber
.u
.AsULONG
,
1432 PCI_COMMON_HDR_LENGTH
);
1433 if (DataSize
!= PCI_COMMON_HDR_LENGTH
)
1435 if (FunctionNumber
== 0)
1445 sprintf (VendorIdString
, "%04hx", PciConfig
.VendorID
);
1446 sprintf (DeviceIdString
, "%04hx", PciConfig
.DeviceID
);
1448 if (!_strnicmp(VendorIdString
, HwInitializationData
->VendorId
, HwInitializationData
->VendorIdLength
) &&
1449 !_strnicmp(DeviceIdString
, HwInitializationData
->DeviceId
, HwInitializationData
->DeviceIdLength
))
1451 DPRINT ("Found device 0x%04hx 0x%04hx at %1lu %2lu %1lu\n",
1455 SlotNumber
.u
.bits
.DeviceNumber
,
1456 SlotNumber
.u
.bits
.FunctionNumber
);
1458 PortConfig
->BusInterruptLevel
=
1459 PortConfig
->BusInterruptVector
= PciConfig
.u
.type0
.InterruptLine
;
1460 PortConfig
->SlotNumber
= SlotNumber
.u
.AsULONG
;
1462 /* Initialize access ranges */
1463 if (PortConfig
->NumberOfAccessRanges
> 0)
1465 if (PortConfig
->NumberOfAccessRanges
> PCI_TYPE0_ADDRESSES
)
1466 PortConfig
->NumberOfAccessRanges
= PCI_TYPE0_ADDRESSES
;
1468 for (i
= 0; i
< PortConfig
->NumberOfAccessRanges
; i
++)
1470 (*PortConfig
->AccessRanges
)[i
].RangeStart
.QuadPart
=
1471 PciConfig
.u
.type0
.BaseAddresses
[i
] & PCI_ADDRESS_IO_ADDRESS_MASK
;
1472 if ((*PortConfig
->AccessRanges
)[i
].RangeStart
.QuadPart
!= 0)
1474 RangeLength
= (ULONG
)-1;
1475 HalSetBusDataByOffset (PCIConfiguration
,
1477 SlotNumber
.u
.AsULONG
,
1478 (PVOID
)&RangeLength
,
1479 0x10 + (i
* sizeof(ULONG
)),
1482 HalGetBusDataByOffset (PCIConfiguration
,
1484 SlotNumber
.u
.AsULONG
,
1485 (PVOID
)&RangeLength
,
1486 0x10 + (i
* sizeof(ULONG
)),
1489 HalSetBusDataByOffset (PCIConfiguration
,
1491 SlotNumber
.u
.AsULONG
,
1492 (PVOID
)&PciConfig
.u
.type0
.BaseAddresses
[i
],
1493 0x10 + (i
* sizeof(ULONG
)),
1495 if (RangeLength
!= 0)
1497 (*PortConfig
->AccessRanges
)[i
].RangeLength
=
1498 -(RangeLength
& PCI_ADDRESS_IO_ADDRESS_MASK
);
1499 (*PortConfig
->AccessRanges
)[i
].RangeInMemory
=
1500 !(PciConfig
.u
.type0
.BaseAddresses
[i
] & PCI_ADDRESS_IO_SPACE
);
1502 DPRINT("RangeStart 0x%lX RangeLength 0x%lX RangeInMemory %s\n",
1503 PciConfig
.u
.type0
.BaseAddresses
[i
] & PCI_ADDRESS_IO_ADDRESS_MASK
,
1504 -(RangeLength
& PCI_ADDRESS_IO_ADDRESS_MASK
),
1505 (PciConfig
.u
.type0
.BaseAddresses
[i
] & PCI_ADDRESS_IO_SPACE
)?"FALSE":"TRUE");
1511 NextSlotNumber
->u
.bits
.DeviceNumber
= DeviceNumber
;
1512 NextSlotNumber
->u
.bits
.FunctionNumber
= FunctionNumber
;
1514 PortConfig
->SlotNumber
= NextSlotNumber
->u
.AsULONG
;
1516 NextSlotNumber
->u
.bits
.FunctionNumber
+= 1;
1522 if (FunctionNumber
== 0 && !(PciConfig
.HeaderType
& PCI_MULTIFUNCTION
))
1527 NextSlotNumber
->u
.bits
.FunctionNumber
= 0;
1530 DPRINT ("No device found\n");
1537 /**********************************************************************
1539 * ScsiPortCreateClose
1542 * Answer requests for Create/Close calls: a null operation.
1549 * Pointer to a device object.
1552 * Pointer to an IRP.
1558 static NTSTATUS STDCALL
1559 ScsiPortCreateClose(IN PDEVICE_OBJECT DeviceObject
,
1562 DPRINT("ScsiPortCreateClose()\n");
1564 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1565 Irp
->IoStatus
.Information
= FILE_OPENED
;
1567 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1569 return(STATUS_SUCCESS
);
1573 /**********************************************************************
1575 * ScsiPortDispatchScsi
1578 * Answer requests for SCSI calls
1584 * Standard dispatch arguments
1590 static NTSTATUS STDCALL
1591 ScsiPortDispatchScsi(IN PDEVICE_OBJECT DeviceObject
,
1594 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
1595 PSCSI_PORT_LUN_EXTENSION LunExtension
;
1596 PIO_STACK_LOCATION Stack
;
1597 PSCSI_REQUEST_BLOCK Srb
;
1598 NTSTATUS Status
= STATUS_SUCCESS
;
1601 DPRINT("ScsiPortDispatchScsi(DeviceObject %p Irp %p)\n",
1604 DeviceExtension
= DeviceObject
->DeviceExtension
;
1605 Stack
= IoGetCurrentIrpStackLocation(Irp
);
1607 Srb
= Stack
->Parameters
.Scsi
.Srb
;
1610 Status
= STATUS_UNSUCCESSFUL
;
1612 Irp
->IoStatus
.Status
= Status
;
1613 Irp
->IoStatus
.Information
= 0;
1615 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1620 DPRINT("Srb: %p\n", Srb
);
1621 DPRINT("Srb->Function: %lu\n", Srb
->Function
);
1622 DPRINT("PathId: %lu TargetId: %lu Lun: %lu\n", Srb
->PathId
, Srb
->TargetId
, Srb
->Lun
);
1624 LunExtension
= SpiGetLunExtension(DeviceExtension
,
1628 if (LunExtension
== NULL
)
1630 Status
= STATUS_NO_SUCH_DEVICE
;
1632 Srb
->SrbStatus
= SRB_STATUS_NO_DEVICE
;
1633 Irp
->IoStatus
.Status
= Status
;
1634 Irp
->IoStatus
.Information
= 0;
1636 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1641 switch (Srb
->Function
)
1643 case SRB_FUNCTION_EXECUTE_SCSI
:
1644 case SRB_FUNCTION_IO_CONTROL
:
1645 IoMarkIrpPending(Irp
);
1646 Srb
->OriginalRequest
= LunExtension
;
1647 Irp
->Tail
.Overlay
.DriverContext
[3] = Srb
;
1648 SpiProcessRequests(DeviceExtension
, Irp
);
1649 return(STATUS_PENDING
);
1651 case SRB_FUNCTION_SHUTDOWN
:
1652 case SRB_FUNCTION_FLUSH
:
1653 if (DeviceExtension
->PortConfig
->CachesData
== TRUE
)
1655 IoMarkIrpPending(Irp
);
1656 Srb
->OriginalRequest
= LunExtension
;
1657 Irp
->Tail
.Overlay
.DriverContext
[3] = Srb
;
1658 SpiProcessRequests(DeviceExtension
, Irp
);
1659 return(STATUS_PENDING
);
1663 case SRB_FUNCTION_CLAIM_DEVICE
:
1664 DPRINT (" SRB_FUNCTION_CLAIM_DEVICE\n");
1666 /* Reference device object and keep the device object */
1667 ObReferenceObject(DeviceObject
);
1668 LunExtension
->DeviceObject
= DeviceObject
;
1669 LunExtension
->DeviceClaimed
= TRUE
;
1670 Srb
->DataBuffer
= DeviceObject
;
1673 case SRB_FUNCTION_RELEASE_DEVICE
:
1674 DPRINT (" SRB_FUNCTION_RELEASE_DEVICE\n");
1675 DPRINT ("PathId: %lu TargetId: %lu Lun: %lu\n",
1676 Srb
->PathId
, Srb
->TargetId
, Srb
->Lun
);
1678 /* Dereference device object and clear the device object */
1679 ObDereferenceObject(LunExtension
->DeviceObject
);
1680 LunExtension
->DeviceObject
= NULL
;
1681 LunExtension
->DeviceClaimed
= FALSE
;
1685 DPRINT1("SRB function not implemented (Function %lu)\n", Srb
->Function
);
1686 Status
= STATUS_NOT_IMPLEMENTED
;
1690 Irp
->IoStatus
.Status
= Status
;
1691 Irp
->IoStatus
.Information
= DataSize
;
1693 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1699 /**********************************************************************
1701 * ScsiPortDeviceControl
1704 * Answer requests for device control calls
1710 * Standard dispatch arguments
1716 static NTSTATUS STDCALL
1717 ScsiPortDeviceControl(IN PDEVICE_OBJECT DeviceObject
,
1720 PIO_STACK_LOCATION Stack
;
1721 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
1722 NTSTATUS Status
= STATUS_SUCCESS
;
1724 DPRINT("ScsiPortDeviceControl()\n");
1726 Irp
->IoStatus
.Information
= 0;
1729 Stack
= IoGetCurrentIrpStackLocation(Irp
);
1730 DeviceExtension
= DeviceObject
->DeviceExtension
;
1732 switch (Stack
->Parameters
.DeviceIoControl
.IoControlCode
)
1734 case IOCTL_SCSI_GET_DUMP_POINTERS
:
1736 PDUMP_POINTERS DumpPointers
;
1737 DPRINT(" IOCTL_SCSI_GET_DUMP_POINTERS\n");
1738 DumpPointers
= (PDUMP_POINTERS
)Irp
->AssociatedIrp
.SystemBuffer
;
1739 DumpPointers
->DeviceObject
= DeviceObject
;
1741 Irp
->IoStatus
.Information
= sizeof(DUMP_POINTERS
);
1745 case IOCTL_SCSI_GET_CAPABILITIES
:
1747 DPRINT(" IOCTL_SCSI_GET_CAPABILITIES\n");
1749 *((PIO_SCSI_CAPABILITIES
*)Irp
->AssociatedIrp
.SystemBuffer
) =
1750 DeviceExtension
->PortCapabilities
;
1752 Irp
->IoStatus
.Information
= sizeof(PIO_SCSI_CAPABILITIES
);
1756 case IOCTL_SCSI_GET_INQUIRY_DATA
:
1758 DPRINT(" IOCTL_SCSI_GET_INQUIRY_DATA\n");
1760 /* Copy inquiry data to the port device extension */
1761 Irp
->IoStatus
.Information
=
1762 SpiGetInquiryData(DeviceExtension
,
1763 Irp
->AssociatedIrp
.SystemBuffer
);
1764 DPRINT("Inquiry data size: %lu\n", Irp
->IoStatus
.Information
);
1768 case IOCTL_SCSI_PASS_THROUGH
:
1769 DPRINT(" IOCTL_SCSI_PASS_THROUGH\n");
1770 Status
= STATUS_NOT_IMPLEMENTED
;
1773 case IOCTL_SCSI_PASS_THROUGH_DIRECT
:
1774 DPRINT(" IOCTL_SCSI_PASS_THROUGH_DIRECT\n");
1775 Status
= STATUS_NOT_IMPLEMENTED
;
1778 case IOCTL_SCSI_MINIPORT
:
1779 DPRINT1(" IOCTL_SCSI_MINIPORT\n");
1780 DPRINT1(" Signature: %.8s\n", ((PSRB_IO_CONTROL
)Irp
->AssociatedIrp
.SystemBuffer
)->Signature
);
1781 DPRINT1(" ControlCode: 0x%lX\n", ((PSRB_IO_CONTROL
)Irp
->AssociatedIrp
.SystemBuffer
)->ControlCode
);
1782 return SpiScsiMiniport(DeviceObject
, Irp
);
1785 DPRINT1(" unknown ioctl code: 0x%lX\n",
1786 Stack
->Parameters
.DeviceIoControl
.IoControlCode
);
1787 Status
= STATUS_INVALID_DEVICE_REQUEST
;
1791 Irp
->IoStatus
.Status
= Status
;
1792 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1797 static NTSTATUS STDCALL
1798 SpiCompletion(IN PDEVICE_OBJECT DeviceObject
,
1802 PSCSI_REQUEST_BLOCK Srb
;
1804 DPRINT("SpiCompletion(DeviceObject %x, Irp %x, Context %x)\n",
1805 DeviceObject
, Irp
, Context
);
1807 Srb
= (PSCSI_REQUEST_BLOCK
)Context
;
1808 Irp
->IoStatus
.Information
= 0;
1810 switch (SRB_STATUS(Srb
->SrbStatus
))
1812 case SRB_STATUS_SUCCESS
:
1813 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1814 Irp
->IoStatus
.Information
= Srb
->DataTransferLength
;
1817 case SRB_STATUS_INVALID_PATH_ID
:
1818 case SRB_STATUS_INVALID_TARGET_ID
:
1819 case SRB_STATUS_INVALID_LUN
:
1820 case SRB_STATUS_NO_HBA
:
1821 Irp
->IoStatus
.Status
= STATUS_NO_SUCH_DEVICE
;
1824 case SRB_STATUS_NO_DEVICE
:
1825 Irp
->IoStatus
.Status
= STATUS_DEVICE_NOT_CONNECTED
;
1828 case SRB_STATUS_BUSY
:
1829 Irp
->IoStatus
.Status
= STATUS_DEVICE_BUSY
;
1832 case SRB_STATUS_DATA_OVERRUN
:
1833 Irp
->IoStatus
.Status
= STATUS_DATA_OVERRUN
;
1834 Irp
->IoStatus
.Information
= Srb
->DataTransferLength
;
1837 case SRB_STATUS_INVALID_REQUEST
:
1838 Irp
->IoStatus
.Status
= STATUS_INVALID_DEVICE_REQUEST
;
1842 Irp
->IoStatus
.Status
= STATUS_IO_DEVICE_ERROR
;
1848 if (Irp
->PendingReturned
)
1850 IoMarkIrpPending (Irp
);
1852 return Irp
->IoStatus
.Status
;
1856 SpiScsiMiniport(IN PDEVICE_OBJECT DeviceObject
,
1859 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
1860 PSRB_IO_CONTROL SrbIoControl
;
1861 PIO_STACK_LOCATION IrpStack
;
1862 PSCSI_REQUEST_BLOCK Srb
;
1863 PSCSI_PORT_LUN_EXTENSION LunExtension
;
1865 DPRINT("SpiScsiMiniport(DeviceObject %x, Irp %x)\n",
1868 DeviceExtension
= DeviceObject
->DeviceExtension
;
1869 SrbIoControl
= (PSRB_IO_CONTROL
)Irp
->AssociatedIrp
.SystemBuffer
;
1871 IrpStack
= IoGetCurrentIrpStackLocation(Irp
);
1872 if (IrpStack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(SRB_IO_CONTROL
) + sizeof(SENDCMDINPARAMS
) - 1)
1874 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
1875 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1876 return STATUS_INVALID_PARAMETER
;
1878 if (IrpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(SRB_IO_CONTROL
) + SrbIoControl
->Length
)
1880 Irp
->IoStatus
.Information
= sizeof(SRB_IO_CONTROL
) + SrbIoControl
->Length
;
1881 Irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
1882 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1883 return STATUS_BUFFER_TOO_SMALL
;
1885 if (IsListEmpty(&DeviceExtension
->LunExtensionListHead
))
1887 Irp
->IoStatus
.Status
= STATUS_NO_SUCH_DEVICE
;
1888 Irp
->IoStatus
.Information
= 0;
1889 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1890 return STATUS_NO_SUCH_DEVICE
;
1893 Srb
= ExAllocatePool(NonPagedPool
, sizeof(SCSI_REQUEST_BLOCK
));
1896 Irp
->IoStatus
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
1897 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1898 return STATUS_INSUFFICIENT_RESOURCES
;
1900 RtlZeroMemory(Srb
, sizeof(SCSI_REQUEST_BLOCK
));
1901 Srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
1902 Srb
->OriginalRequest
= Irp
;
1903 Srb
->Function
= SRB_FUNCTION_IO_CONTROL
;
1904 Srb
->DataBuffer
= (PVOID
)SrbIoControl
;
1905 Srb
->DataTransferLength
= sizeof(SRB_IO_CONTROL
) + SrbIoControl
->Length
;
1907 /* We using the first extension from the list. The miniport driver is responsible to find the correct device. */
1908 LunExtension
= CONTAINING_RECORD(DeviceExtension
->LunExtensionListHead
.Flink
,
1909 SCSI_PORT_LUN_EXTENSION
,
1911 Srb
->PathId
= LunExtension
->PathId
;
1912 Srb
->TargetId
= LunExtension
->TargetId
;
1913 Srb
->Lun
= LunExtension
->Lun
;
1915 IrpStack
= IoGetNextIrpStackLocation(Irp
);
1917 IrpStack
->MajorFunction
= IRP_MJ_SCSI
;
1918 IrpStack
->Parameters
.Scsi
.Srb
= Srb
;
1920 IoSetCompletionRoutine(Irp
,
1927 return IoCallDriver(DeviceObject
, Irp
);
1931 SpiAllocateSrbExtension(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
1932 PSCSI_REQUEST_BLOCK Srb
)
1936 DPRINT("SpiAllocateSrbExtension\n");
1938 DPRINT("DeviceExtension->VirtualAddress %x, DeviceExtension->SrbExtensionSize %x\n",
1939 DeviceExtension
->VirtualAddress
, DeviceExtension
->SrbExtensionSize
);
1941 Srb
->SrbExtension
= NULL
;
1942 if (DeviceExtension
->VirtualAddress
!= NULL
&&
1943 DeviceExtension
->SrbExtensionSize
> 0)
1945 index
= RtlFindClearBitsAndSet(&DeviceExtension
->SrbExtensionAllocMap
, 1, 0);
1946 if (index
!= 0xffffffff)
1948 DeviceExtension
->CurrentSrbExtensions
++;
1949 Srb
->SrbExtension
= (PVOID
)((ULONG_PTR
)DeviceExtension
->VirtualAddress
+ index
* DeviceExtension
->SrbExtensionSize
);
1952 DPRINT("%x\n", Srb
->SrbExtension
);
1956 SpiFreeSrbExtension(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
1957 PSCSI_REQUEST_BLOCK Srb
)
1961 if (DeviceExtension
->VirtualAddress
!= NULL
&&
1962 DeviceExtension
->SrbExtensionSize
> 0 &&
1963 Srb
->SrbExtension
!= NULL
)
1965 index
= ((ULONG_PTR
)Srb
->SrbExtension
- (ULONG_PTR
)DeviceExtension
->VirtualAddress
) / DeviceExtension
->SrbExtensionSize
;
1966 RtlClearBits(&DeviceExtension
->SrbExtensionAllocMap
, index
, 1);
1967 DeviceExtension
->CurrentSrbExtensions
--;
1969 Srb
->SrbExtension
= NULL
;
1973 static BOOLEAN STDCALL
1974 ScsiPortStartPacket(IN OUT PVOID Context
)
1976 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
1977 PSCSI_REQUEST_BLOCK Srb
;
1979 PIO_STACK_LOCATION IrpStack
;
1981 DPRINT("ScsiPortStartPacket(Context %x) called\n", Context
);
1983 Srb
= (PSCSI_REQUEST_BLOCK
)Context
;
1984 Irp
= (PIRP
)Srb
->OriginalRequest
;
1985 IrpStack
= IoGetCurrentIrpStackLocation(Irp
);
1986 DeviceExtension
= IrpStack
->DeviceObject
->DeviceExtension
;
1988 return(DeviceExtension
->HwStartIo(&DeviceExtension
->MiniPortDeviceExtension
,
1993 static PSCSI_PORT_LUN_EXTENSION
1994 SpiAllocateLunExtension (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
1999 PSCSI_PORT_LUN_EXTENSION LunExtension
;
2000 ULONG LunExtensionSize
;
2002 DPRINT("SpiAllocateLunExtension (%p %u %u %u)\n",
2003 DeviceExtension
, PathId
, TargetId
, Lun
);
2006 sizeof(SCSI_PORT_LUN_EXTENSION
) + DeviceExtension
->LunExtensionSize
;
2007 DPRINT("LunExtensionSize %lu\n", LunExtensionSize
);
2009 LunExtension
= ExAllocatePool(NonPagedPool
,
2011 if (LunExtension
== NULL
)
2016 RtlZeroMemory(LunExtension
,
2019 InsertTailList(&DeviceExtension
->LunExtensionListHead
,
2020 &LunExtension
->List
);
2022 LunExtension
->PathId
= PathId
;
2023 LunExtension
->TargetId
= TargetId
;
2024 LunExtension
->Lun
= Lun
;
2026 LunExtension
->PendingIrpCount
= 0;
2027 LunExtension
->ActiveIrpCount
= 0;
2029 LunExtension
->NextIrp
= NULL
;
2031 return LunExtension
;
2036 SpiRemoveLunExtension (IN PSCSI_PORT_LUN_EXTENSION LunExtension
)
2038 DPRINT("SpiRemoveLunExtension(%p) called\n",
2041 if (LunExtension
== NULL
)
2044 RemoveEntryList (&LunExtension
->List
);
2047 /* Release LUN extersion data */
2050 ExFreePool (LunExtension
);
2056 static PSCSI_PORT_LUN_EXTENSION
2057 SpiGetLunExtension (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
2062 PSCSI_PORT_LUN_EXTENSION LunExtension
;
2065 DPRINT("SpiGetLunExtension(%p %u %u %u) called\n",
2066 DeviceExtension
, PathId
, TargetId
, Lun
);
2068 if (IsListEmpty(&DeviceExtension
->LunExtensionListHead
))
2071 Entry
= DeviceExtension
->LunExtensionListHead
.Flink
;
2072 while (Entry
!= &DeviceExtension
->LunExtensionListHead
)
2074 LunExtension
= CONTAINING_RECORD(Entry
,
2075 SCSI_PORT_LUN_EXTENSION
,
2077 if (LunExtension
->PathId
== PathId
&&
2078 LunExtension
->TargetId
== TargetId
&&
2079 LunExtension
->Lun
== Lun
)
2081 return LunExtension
;
2084 Entry
= Entry
->Flink
;
2092 SpiSendInquiry (IN PDEVICE_OBJECT DeviceObject
,
2093 IN OUT PSCSI_REQUEST_BLOCK Srb
,
2094 IN OUT PIO_STATUS_BLOCK IoStatusBlock
,
2095 IN OUT PKEVENT Event
)
2097 PIO_STACK_LOCATION IrpStack
;
2101 DPRINT ("SpiSendInquiry() called\n");
2104 KeInitializeEvent (Event
,
2108 Irp
= IoBuildDeviceIoControlRequest (IOCTL_SCSI_EXECUTE_OUT
,
2113 Srb
->DataTransferLength
,
2119 DPRINT("IoBuildDeviceIoControlRequest() failed\n");
2120 return STATUS_INSUFFICIENT_RESOURCES
;
2123 /* Attach Srb to the Irp */
2124 IrpStack
= IoGetNextIrpStackLocation (Irp
);
2125 IrpStack
->Parameters
.Scsi
.Srb
= Srb
;
2126 Srb
->OriginalRequest
= Irp
;
2128 /* Call the driver */
2129 Status
= IoCallDriver (DeviceObject
,
2136 SpiScanAdapter (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
)
2138 PSCSI_REQUEST_BLOCK Srb
;
2142 PSCSI_PORT_SCAN_ADAPTER ScanDataArray
;
2143 PSCSI_PORT_SCAN_ADAPTER ScanData
;
2149 PKWAIT_BLOCK WaitBlockArray
;
2151 DPRINT ("SpiScanAdapter() called\n");
2153 MaxCount
= DeviceExtension
->PortConfig
->NumberOfBuses
*
2154 DeviceExtension
->PortConfig
->MaximumNumberOfTargets
;
2156 ScanDataArray
= ExAllocatePool(NonPagedPool
, MaxCount
* (sizeof(SCSI_PORT_SCAN_ADAPTER
) + sizeof(PVOID
) + sizeof(KWAIT_BLOCK
)));
2157 if (ScanDataArray
== NULL
)
2161 EventArray
= (PVOID
*)((PUCHAR
)ScanDataArray
+ MaxCount
* sizeof(SCSI_PORT_SCAN_ADAPTER
));
2162 WaitBlockArray
= (PKWAIT_BLOCK
)((PUCHAR
)EventArray
+ MaxCount
* sizeof(PVOID
));
2164 for (Bus
= 0; Bus
< DeviceExtension
->PortConfig
->NumberOfBuses
; Bus
++)
2166 for (Target
= 0; Target
< DeviceExtension
->PortConfig
->MaximumNumberOfTargets
; Target
++)
2168 ScanData
= &ScanDataArray
[Bus
* DeviceExtension
->PortConfig
->MaximumNumberOfTargets
+ Target
];
2169 ScanData
->Bus
= Bus
;
2170 ScanData
->Target
= Target
;
2172 ScanData
->Active
= FALSE
;
2179 for (i
= 0; i
< MaxCount
; i
++)
2181 ScanData
= &ScanDataArray
[i
];
2182 Srb
= &ScanData
->Srb
;
2183 if (ScanData
->Active
)
2185 if (ScanData
->Status
== STATUS_PENDING
&&
2186 0 == KeReadStateEvent(&ScanData
->Event
))
2193 ScanData
->Status
= ScanData
->IoStatusBlock
.Status
;
2195 ScanData
->Active
= FALSE
;
2196 DPRINT ("Target %lu Lun %lu\n", ScanData
->Target
, ScanData
->Lun
);
2197 DPRINT ("Status %lx Srb.SrbStatus %x\n", ScanData
->Status
, Srb
->SrbStatus
);
2198 DPRINT ("DeviceTypeQualifier %x\n", ((PINQUIRYDATA
)Srb
->DataBuffer
)->DeviceTypeQualifier
);
2200 if (NT_SUCCESS(ScanData
->Status
) &&
2201 (Srb
->SrbStatus
== SRB_STATUS_SUCCESS
||
2202 (Srb
->SrbStatus
== SRB_STATUS_DATA_OVERRUN
&&
2205 * The NT 4.0 driver from an inic950 based scsi controller
2206 * returns only 4 byte of inquiry data, but the device name
2207 * is visible on NT 4.0. We must implement an other way
2208 * to get the complete inquiry data.
2210 Srb
->DataTransferLength
>= /*INQUIRYDATABUFFERSIZE*/4)) &&
2211 ((PINQUIRYDATA
)Srb
->DataBuffer
)->DeviceTypeQualifier
== 0)
2213 /* Copy inquiry data */
2214 RtlCopyMemory (&ScanData
->LunExtension
->InquiryData
,
2216 min(sizeof(INQUIRYDATA
), Srb
->DataTransferLength
));
2221 SpiRemoveLunExtension (ScanData
->LunExtension
);
2222 ScanData
->Lun
= SCSI_MAXIMUM_LOGICAL_UNITS
;
2225 if (ScanData
->Lun
>= SCSI_MAXIMUM_LOGICAL_UNITS
)
2229 RtlZeroMemory(Srb
, sizeof(SCSI_REQUEST_BLOCK
));
2230 Srb
->SrbFlags
= SRB_FLAGS_DATA_IN
;
2231 Srb
->DataBuffer
= ScanData
->DataBuffer
;
2232 Srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
2233 Srb
->DataTransferLength
= 255; //256;
2235 Srb
->Lun
= ScanData
->Lun
;
2236 Srb
->PathId
= ScanData
->Bus
;
2237 Srb
->TargetId
= ScanData
->Target
;
2238 Srb
->SrbStatus
= SRB_STATUS_SUCCESS
;
2239 Srb
->TimeOutValue
= 2;
2240 Cdb
= (PCDB
) &Srb
->Cdb
;
2242 Cdb
->CDB6INQUIRY
.OperationCode
= SCSIOP_INQUIRY
;
2243 Cdb
->CDB6INQUIRY
.AllocationLength
= 255;
2244 Cdb
->CDB6INQUIRY
.LogicalUnitNumber
= ScanData
->Lun
;
2246 RtlZeroMemory(Srb
->DataBuffer
, 256);
2248 ScanData
->LunExtension
= SpiAllocateLunExtension (DeviceExtension
,
2252 if (ScanData
->LunExtension
== NULL
)
2254 DPRINT1("Failed to allocate the LUN extension!\n");
2255 ScanData
->Lun
= SCSI_MAXIMUM_LOGICAL_UNITS
;
2258 ScanData
->Status
= SpiSendInquiry (DeviceExtension
->DeviceObject
,
2260 &ScanData
->IoStatusBlock
,
2262 ScanData
->Active
= TRUE
;
2264 if (ScanData
->Status
== STATUS_PENDING
)
2266 EventArray
[WaitCount
] = &ScanData
->Event
;
2270 if (WaitCount
> 0 && WaitCount
== ActiveCount
)
2272 KeWaitForMultipleObjects(WaitCount
,
2282 while (ActiveCount
> 0);
2284 ExFreePool(ScanDataArray
);
2286 DPRINT ("SpiScanAdapter() done\n");
2291 SpiGetInquiryData(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
2292 OUT PSCSI_ADAPTER_BUS_INFO AdapterBusInfo
)
2294 PSCSI_PORT_LUN_EXTENSION LunExtension
;
2295 PSCSI_INQUIRY_DATA UnitInfo
, PrevUnit
;
2301 DPRINT("SpiGetInquiryData() called\n");
2303 /* Copy inquiry data to the port device extension */
2304 AdapterBusInfo
->NumberOfBuses
= DeviceExtension
->PortConfig
->NumberOfBuses
;
2306 UnitInfo
= (PSCSI_INQUIRY_DATA
)
2307 ((PUCHAR
)AdapterBusInfo
+ sizeof(SCSI_ADAPTER_BUS_INFO
) +
2308 (sizeof(SCSI_BUS_DATA
) * (AdapterBusInfo
->NumberOfBuses
- 1)));
2310 for (Bus
= 0; Bus
< AdapterBusInfo
->NumberOfBuses
; Bus
++)
2312 AdapterBusInfo
->BusData
[Bus
].InitiatorBusId
=
2313 DeviceExtension
->PortConfig
->InitiatorBusId
[Bus
];
2314 AdapterBusInfo
->BusData
[Bus
].InquiryDataOffset
=
2315 (ULONG
)((PUCHAR
)UnitInfo
- (PUCHAR
)AdapterBusInfo
);
2320 for (Target
= 0; Target
< DeviceExtension
->PortConfig
->MaximumNumberOfTargets
; Target
++)
2322 for (Lun
= 0; Lun
< SCSI_MAXIMUM_LOGICAL_UNITS
; Lun
++)
2324 LunExtension
= SpiGetLunExtension(DeviceExtension
,
2328 if (LunExtension
!= NULL
)
2330 DPRINT("(Bus %lu Target %lu Lun %lu)\n",
2332 RtlZeroMemory(UnitInfo
, sizeof(*UnitInfo
));
2333 UnitInfo
->PathId
= Bus
;
2334 UnitInfo
->TargetId
= Target
;
2335 UnitInfo
->Lun
= Lun
;
2336 UnitInfo
->InquiryDataLength
= INQUIRYDATABUFFERSIZE
;
2337 RtlCopyMemory (&UnitInfo
->InquiryData
,
2338 &LunExtension
->InquiryData
,
2339 INQUIRYDATABUFFERSIZE
);
2340 if (PrevUnit
!= NULL
)
2342 PrevUnit
->NextInquiryDataOffset
=
2343 (ULONG
)((ULONG_PTR
)UnitInfo
-(ULONG_PTR
)AdapterBusInfo
);
2345 PrevUnit
= UnitInfo
;
2346 UnitInfo
= (PSCSI_INQUIRY_DATA
)((PUCHAR
)UnitInfo
+ sizeof(SCSI_INQUIRY_DATA
)+INQUIRYDATABUFFERSIZE
-1);
2351 DPRINT("UnitCount: %lu\n", UnitCount
);
2352 AdapterBusInfo
->BusData
[Bus
].NumberOfLogicalUnits
= UnitCount
;
2355 AdapterBusInfo
->BusData
[Bus
].InquiryDataOffset
= 0;
2359 DPRINT("Data size: %lu\n", (ULONG
)UnitInfo
- (ULONG
)AdapterBusInfo
);
2361 return (ULONG
)((PUCHAR
)UnitInfo
-(PUCHAR
)AdapterBusInfo
);
2365 static BOOLEAN STDCALL
2366 ScsiPortIsr(IN PKINTERRUPT Interrupt
,
2367 IN PVOID ServiceContext
)
2369 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
2371 DPRINT("ScsiPortIsr() called!\n");
2373 DeviceExtension
= (PSCSI_PORT_DEVICE_EXTENSION
)ServiceContext
;
2375 return DeviceExtension
->HwInterrupt(&DeviceExtension
->MiniPortDeviceExtension
);
2386 // IN PDEVICE_OBJECT DpcDeviceObject
2388 // IN PVOID DpcContext
2391 ScsiPortDpc(IN PKDPC Dpc
,
2392 IN PDEVICE_OBJECT DpcDeviceObject
,
2394 IN PVOID DpcContext
)
2396 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
2398 DPRINT("ScsiPortDpc(Dpc %p DpcDeviceObject %p DpcIrp %p DpcContext %p)\n",
2399 Dpc
, DpcDeviceObject
, DpcIrp
, DpcContext
);
2401 DeviceExtension
= (PSCSI_PORT_DEVICE_EXTENSION
)DpcContext
;
2403 SpiProcessRequests(DeviceExtension
, NULL
);
2405 DPRINT("ScsiPortDpc() done\n");
2411 // This function handles timeouts and other time delayed processing
2416 // IN PDEVICE_OBJECT DeviceObject Device object registered with timer
2417 // IN PVOID Context the Controller extension for the
2418 // controller the device is on
2421 ScsiPortIoTimer(PDEVICE_OBJECT DeviceObject
,
2424 DPRINT1("ScsiPortIoTimer()\n");
2428 static PSCSI_REQUEST_BLOCK
2429 ScsiPortInitSenseRequestSrb(PSCSI_REQUEST_BLOCK OriginalSrb
)
2431 PSCSI_REQUEST_BLOCK Srb
;
2435 Length
= sizeof(SCSI_REQUEST_BLOCK
) + sizeof(SENSE_DATA
) + 32;
2436 Srb
= ExAllocatePoolWithTag(NonPagedPool
,
2438 TAG('S', 'S', 'r', 'b'));
2444 RtlZeroMemory(Srb
, Length
);
2446 Srb
->PathId
= OriginalSrb
->PathId
;
2447 Srb
->TargetId
= OriginalSrb
->TargetId
;
2448 Srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
2449 Srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
2450 Srb
->SrbFlags
= SRB_FLAGS_DATA_IN
| SRB_FLAGS_DISABLE_SYNCH_TRANSFER
;
2451 Srb
->OriginalRequest
= OriginalSrb
->OriginalRequest
;
2453 Srb
->TimeOutValue
= 4;
2456 /* The DataBuffer must be located in contiguous physical memory if
2457 * the miniport driver uses dma for the sense info. The size of
2458 * the sense data is 18 byte. If the buffer starts at a 32 byte
2459 * boundary than is the buffer always in one memory page.
2461 Srb
->DataBuffer
= (PVOID
)ROUND_UP((ULONG_PTR
)(Srb
+ 1), 32);
2462 Srb
->DataTransferLength
= sizeof(SENSE_DATA
);
2464 Cdb
= (PCDB
)Srb
->Cdb
;
2465 Cdb
->CDB6INQUIRY
.OperationCode
= SCSIOP_REQUEST_SENSE
;
2466 Cdb
->CDB6INQUIRY
.AllocationLength
= sizeof(SENSE_DATA
);
2471 /**********************************************************************
2476 * Builds the registry device map of all device which are attached
2477 * to the given SCSI HBA port. The device map is located at:
2478 * \Registry\Machine\DeviceMap\Scsi
2488 * Name of registry driver service key.
2495 SpiBuildDeviceMap (PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
2496 PUNICODE_STRING RegistryPath
)
2498 PSCSI_PORT_LUN_EXTENSION LunExtension
;
2499 OBJECT_ATTRIBUTES ObjectAttributes
;
2500 UNICODE_STRING KeyName
=
2501 RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\Hardware\\DeviceMap\\Scsi");
2502 UNICODE_STRING ValueName
;
2503 WCHAR NameBuffer
[64];
2506 HANDLE ScsiPortKey
= NULL
;
2507 HANDLE ScsiBusKey
= NULL
;
2508 HANDLE ScsiInitiatorKey
= NULL
;
2509 HANDLE ScsiTargetKey
= NULL
;
2510 HANDLE ScsiLunKey
= NULL
;
2513 ULONG CurrentTarget
;
2520 DPRINT("SpiBuildDeviceMap() called\n");
2522 if (DeviceExtension
== NULL
|| RegistryPath
== NULL
)
2524 DPRINT1("Invalid parameter\n");
2525 return(STATUS_INVALID_PARAMETER
);
2528 /* Open or create the 'Scsi' subkey */
2529 InitializeObjectAttributes(&ObjectAttributes
,
2531 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
,
2534 Status
= ZwCreateKey(&ScsiKey
,
2539 REG_OPTION_VOLATILE
,
2541 if (!NT_SUCCESS(Status
))
2543 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status
);
2547 /* Create new 'Scsi Port X' subkey */
2548 DPRINT("Scsi Port %lu\n",
2549 DeviceExtension
->PortNumber
);
2551 swprintf(NameBuffer
,
2553 DeviceExtension
->PortNumber
);
2554 RtlInitUnicodeString(&KeyName
,
2556 InitializeObjectAttributes(&ObjectAttributes
,
2561 Status
= ZwCreateKey(&ScsiPortKey
,
2566 REG_OPTION_VOLATILE
,
2569 if (!NT_SUCCESS(Status
))
2571 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status
);
2576 * Create port-specific values
2579 /* Set 'DMA Enabled' (REG_DWORD) value */
2580 UlongData
= (ULONG
)!DeviceExtension
->PortCapabilities
->AdapterUsesPio
;
2581 DPRINT(" DMA Enabled = %s\n", (UlongData
) ? "TRUE" : "FALSE");
2582 RtlInitUnicodeString(&ValueName
,
2584 Status
= ZwSetValueKey(ScsiPortKey
,
2590 if (!NT_SUCCESS(Status
))
2592 DPRINT("ZwSetValueKey('DMA Enabled') failed (Status %lx)\n", Status
);
2593 ZwClose(ScsiPortKey
);
2597 /* Set 'Driver' (REG_SZ) value */
2598 DriverName
= wcsrchr(RegistryPath
->Buffer
, L
'\\') + 1;
2599 RtlInitUnicodeString(&ValueName
,
2601 Status
= ZwSetValueKey(ScsiPortKey
,
2606 (wcslen(DriverName
) + 1) * sizeof(WCHAR
));
2607 if (!NT_SUCCESS(Status
))
2609 DPRINT("ZwSetValueKey('Driver') failed (Status %lx)\n", Status
);
2610 ZwClose(ScsiPortKey
);
2614 /* Set 'Interrupt' (REG_DWORD) value (NT4 only) */
2615 UlongData
= (ULONG
)DeviceExtension
->PortConfig
->BusInterruptLevel
;
2616 DPRINT(" Interrupt = %lu\n", UlongData
);
2617 RtlInitUnicodeString(&ValueName
,
2619 Status
= ZwSetValueKey(ScsiPortKey
,
2625 if (!NT_SUCCESS(Status
))
2627 DPRINT("ZwSetValueKey('Interrupt') failed (Status %lx)\n", Status
);
2628 ZwClose(ScsiPortKey
);
2632 /* Set 'IOAddress' (REG_DWORD) value (NT4 only) */
2633 UlongData
= ScsiPortConvertPhysicalAddressToUlong((*DeviceExtension
->PortConfig
->AccessRanges
)[0].RangeStart
);
2634 DPRINT(" IOAddress = %lx\n", UlongData
);
2635 RtlInitUnicodeString(&ValueName
,
2637 Status
= ZwSetValueKey(ScsiPortKey
,
2643 if (!NT_SUCCESS(Status
))
2645 DPRINT("ZwSetValueKey('IOAddress') failed (Status %lx)\n", Status
);
2646 ZwClose(ScsiPortKey
);
2650 /* Enumerate buses */
2651 for (BusNumber
= 0; BusNumber
< DeviceExtension
->PortConfig
->NumberOfBuses
; BusNumber
++)
2653 /* Create 'Scsi Bus X' key */
2654 DPRINT(" Scsi Bus %lu\n", BusNumber
);
2655 swprintf(NameBuffer
,
2658 RtlInitUnicodeString(&KeyName
,
2660 InitializeObjectAttributes(&ObjectAttributes
,
2665 Status
= ZwCreateKey(&ScsiBusKey
,
2670 REG_OPTION_VOLATILE
,
2672 if (!NT_SUCCESS(Status
))
2674 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status
);
2678 /* Create 'Initiator Id X' key */
2679 DPRINT(" Initiator Id %u\n",
2680 DeviceExtension
->PortConfig
->InitiatorBusId
[BusNumber
]);
2681 swprintf(NameBuffer
,
2683 (unsigned int)(UCHAR
)DeviceExtension
->PortConfig
->InitiatorBusId
[BusNumber
]);
2684 RtlInitUnicodeString(&KeyName
,
2686 InitializeObjectAttributes(&ObjectAttributes
,
2691 Status
= ZwCreateKey(&ScsiInitiatorKey
,
2696 REG_OPTION_VOLATILE
,
2698 if (!NT_SUCCESS(Status
))
2700 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status
);
2704 /* FIXME: Are there any initiator values (??) */
2706 ZwClose(ScsiInitiatorKey
);
2707 ScsiInitiatorKey
= NULL
;
2710 /* Enumerate targets */
2711 CurrentTarget
= (ULONG
)-1;
2712 ScsiTargetKey
= NULL
;
2713 for (Target
= 0; Target
< DeviceExtension
->PortConfig
->MaximumNumberOfTargets
; Target
++)
2715 for (Lun
= 0; Lun
< SCSI_MAXIMUM_LOGICAL_UNITS
; Lun
++)
2717 LunExtension
= SpiGetLunExtension(DeviceExtension
,
2721 if (LunExtension
!= NULL
)
2723 if (Target
!= CurrentTarget
)
2725 /* Close old target key */
2726 if (ScsiTargetKey
!= NULL
)
2728 ZwClose(ScsiTargetKey
);
2729 ScsiTargetKey
= NULL
;
2732 /* Create 'Target Id X' key */
2733 DPRINT(" Target Id %lu\n", Target
);
2734 swprintf(NameBuffer
,
2737 RtlInitUnicodeString(&KeyName
,
2739 InitializeObjectAttributes(&ObjectAttributes
,
2744 Status
= ZwCreateKey(&ScsiTargetKey
,
2749 REG_OPTION_VOLATILE
,
2751 if (!NT_SUCCESS(Status
))
2753 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status
);
2757 CurrentTarget
= Target
;
2760 /* Create 'Logical Unit Id X' key */
2761 DPRINT(" Logical Unit Id %lu\n", Lun
);
2762 swprintf(NameBuffer
,
2763 L
"Logical Unit Id %lu",
2765 RtlInitUnicodeString(&KeyName
,
2767 InitializeObjectAttributes(&ObjectAttributes
,
2772 Status
= ZwCreateKey(&ScsiLunKey
,
2777 REG_OPTION_VOLATILE
,
2779 if (!NT_SUCCESS(Status
))
2781 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status
);
2785 /* Set 'Identifier' (REG_SZ) value */
2786 swprintf(NameBuffer
,
2788 LunExtension
->InquiryData
.VendorId
,
2789 LunExtension
->InquiryData
.ProductId
,
2790 LunExtension
->InquiryData
.ProductRevisionLevel
);
2791 DPRINT(" Identifier = '%S'\n", NameBuffer
);
2792 RtlInitUnicodeString(&ValueName
,
2794 Status
= ZwSetValueKey(ScsiLunKey
,
2799 (wcslen(NameBuffer
) + 1) * sizeof(WCHAR
));
2800 if (!NT_SUCCESS(Status
))
2802 DPRINT("ZwSetValueKey('Identifier') failed (Status %lx)\n", Status
);
2806 /* Set 'Type' (REG_SZ) value */
2807 switch (LunExtension
->InquiryData
.DeviceType
)
2810 TypeName
= L
"DiskPeripheral";
2813 TypeName
= L
"TapePeripheral";
2816 TypeName
= L
"PrinterPeripheral";
2819 TypeName
= L
"WormPeripheral";
2822 TypeName
= L
"CdRomPeripheral";
2825 TypeName
= L
"ScannerPeripheral";
2828 TypeName
= L
"OpticalDiskPeripheral";
2831 TypeName
= L
"MediumChangerPeripheral";
2834 TypeName
= L
"CommunicationPeripheral";
2837 TypeName
= L
"OtherPeripheral";
2840 DPRINT(" Type = '%S'\n", TypeName
);
2841 RtlInitUnicodeString(&ValueName
,
2843 Status
= ZwSetValueKey(ScsiLunKey
,
2848 (wcslen(TypeName
) + 1) * sizeof(WCHAR
));
2849 if (!NT_SUCCESS(Status
))
2851 DPRINT("ZwSetValueKey('Type') failed (Status %lx)\n", Status
);
2855 ZwClose(ScsiLunKey
);
2860 /* Close old target key */
2861 if (ScsiTargetKey
!= NULL
)
2863 ZwClose(ScsiTargetKey
);
2864 ScsiTargetKey
= NULL
;
2868 ZwClose(ScsiBusKey
);
2873 if (ScsiLunKey
!= NULL
)
2874 ZwClose (ScsiLunKey
);
2876 if (ScsiInitiatorKey
!= NULL
)
2877 ZwClose (ScsiInitiatorKey
);
2879 if (ScsiTargetKey
!= NULL
)
2880 ZwClose (ScsiTargetKey
);
2882 if (ScsiBusKey
!= NULL
)
2883 ZwClose (ScsiBusKey
);
2885 if (ScsiPortKey
!= NULL
)
2886 ZwClose (ScsiPortKey
);
2888 DPRINT("SpiBuildDeviceMap() done\n");
2894 SpiRemoveActiveIrp(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
2898 PSCSI_PORT_LUN_EXTENSION LunExtension
;
2900 LunExtension
= Irp
->Tail
.Overlay
.DriverContext
[2];
2901 InterlockedDecrement((PLONG
)&LunExtension
->ActiveIrpCount
);
2902 InterlockedDecrement((PLONG
)&DeviceExtension
->ActiveIrpCount
);
2905 InterlockedExchangePointer(&PrevIrp
->Tail
.Overlay
.DriverContext
[0],
2906 Irp
->Tail
.Overlay
.DriverContext
[0]);
2910 InterlockedExchangePointer(&DeviceExtension
->NextIrp
,
2911 Irp
->Tail
.Overlay
.DriverContext
[0]);
2913 if (LunExtension
->NextIrp
== Irp
)
2915 InterlockedExchangePointer(&LunExtension
->NextIrp
,
2916 Irp
->Tail
.Overlay
.DriverContext
[1]);
2921 CurrentIrp
= LunExtension
->NextIrp
;
2924 if (CurrentIrp
->Tail
.Overlay
.DriverContext
[1] == Irp
)
2926 InterlockedExchangePointer(&CurrentIrp
->Tail
.Overlay
.DriverContext
[1],
2927 Irp
->Tail
.Overlay
.DriverContext
[1]);
2930 CurrentIrp
= CurrentIrp
->Tail
.Overlay
.DriverContext
[1];
2937 SpiAddActiveIrp(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
2940 PSCSI_PORT_LUN_EXTENSION LunExtension
;
2941 PSCSI_REQUEST_BLOCK Srb
;
2942 LunExtension
= Irp
->Tail
.Overlay
.DriverContext
[2];
2943 Srb
= Irp
->Tail
.Overlay
.DriverContext
[3];
2944 Irp
->Tail
.Overlay
.DriverContext
[0] = (PVOID
)DeviceExtension
->NextIrp
;
2945 InterlockedExchangePointer(&DeviceExtension
->NextIrp
, Irp
);
2946 Irp
->Tail
.Overlay
.DriverContext
[1] = (PVOID
)LunExtension
->NextIrp
;
2947 InterlockedExchangePointer(&LunExtension
->NextIrp
, Irp
);
2951 SpiProcessRequests(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
2955 * Using of some fields from Srb and Irp while processing requests:
2958 * Srb->OriginalRequest -> LunExtension
2959 * Irp->Tail.Overlay.DriverContext[3] -> original Srb
2960 * IoStack->Parameters.Scsi.Srb -> original Srb
2962 * Irp is within the pending irp list:
2963 * Srb->OriginalRequest -> LunExtension
2964 * Irp->Tail.Overlay.DriverContext[0] and DriverContext[1] -> ListEntry for queue
2965 * Irp->Tail.Overlay.DriverContext[2] -> sort key (from Srb->QueueSortKey)
2966 * Irp->Tail.Overlay.DriverContext[3] -> current Srb (original or sense request)
2967 * IoStack->Parameters.Scsi.Srb -> original Srb
2969 * Irp is within the active irp list or while other processing:
2970 * Srb->OriginalRequest -> Irp
2971 * Irp->Tail.Overlay.DriverContext[0] -> next irp, DeviceExtension->NextIrp is head.
2972 * Irp->Tail.Overlay.DriverContext[1] -> next irp, LunExtension->NextIrp is head.
2973 * Irp->Tail.Overlay.DriverContext[2] -> LunExtension
2974 * Irp->Tail.Overlay.DriverContext[3] -> current Srb (original or sense request)
2975 * IoStack->Parameters.Scsi.Srb -> original Srb
2977 PIO_STACK_LOCATION IrpStack
;
2978 PSCSI_PORT_LUN_EXTENSION LunExtension
;
2979 PLIST_ENTRY ListEntry
;
2982 LIST_ENTRY NextIrpListHead
;
2983 LIST_ENTRY CompleteIrpListHead
;
2984 PSCSI_REQUEST_BLOCK Srb
;
2985 PSCSI_REQUEST_BLOCK OriginalSrb
;
2988 DPRINT("SpiProcessRequests() called\n");
2990 InitializeListHead(&NextIrpListHead
);
2991 InitializeListHead(&CompleteIrpListHead
);
2993 KeAcquireSpinLock(&DeviceExtension
->Lock
, &oldIrql
);
2997 Srb
= NextIrp
->Tail
.Overlay
.DriverContext
[3];
3000 * Is this the right place to set this flag ?
3002 NextIrp
->Tail
.Overlay
.DriverContext
[2] = (PVOID
)Srb
->QueueSortKey
;
3003 LunExtension
= Srb
->OriginalRequest
;
3005 ListEntry
= DeviceExtension
->PendingIrpListHead
.Flink
;
3006 while (ListEntry
!= &DeviceExtension
->PendingIrpListHead
)
3008 Irp
= CONTAINING_RECORD(ListEntry
, IRP
, Tail
.Overlay
.DriverContext
[0]);
3009 if ((ULONG
)Irp
->Tail
.Overlay
.DriverContext
[2] > Srb
->QueueSortKey
)
3013 ListEntry
= ListEntry
->Flink
;
3015 InsertTailList(ListEntry
, (PLIST_ENTRY
)&NextIrp
->Tail
.Overlay
.DriverContext
[0]);
3016 DeviceExtension
->PendingIrpCount
++;
3017 LunExtension
->PendingIrpCount
++;
3020 while (DeviceExtension
->Flags
& IRP_FLAG_COMPLETE
||
3021 (((DeviceExtension
->SrbExtensionSize
== 0 || DeviceExtension
->CurrentSrbExtensions
< DeviceExtension
->MaxSrbExtensions
) &&
3022 DeviceExtension
->PendingIrpCount
> 0 &&
3023 (DeviceExtension
->Flags
& (IRP_FLAG_NEXT
|IRP_FLAG_NEXT_LU
) || DeviceExtension
->NextIrp
== NULL
))))
3025 DPRINT ("RequestComplete %d, NextRequest %d, NextLuRequest %d, PendingIrpCount %d, ActiveIrpCount %d\n",
3026 DeviceExtension
->Flags
& IRP_FLAG_COMPLETE
? 1 : 0,
3027 DeviceExtension
->Flags
& IRP_FLAG_NEXT
? 1 : 0,
3028 DeviceExtension
->Flags
& IRP_FLAG_NEXT_LU
? 1 : 0,
3029 DeviceExtension
->PendingIrpCount
,
3030 DeviceExtension
->ActiveIrpCount
);
3033 if (DeviceExtension
->Flags
& IRP_FLAG_COMPLETE
)
3035 DeviceExtension
->Flags
&= ~IRP_FLAG_COMPLETE
;
3037 Irp
= DeviceExtension
->NextIrp
;
3040 NextIrp
= (PIRP
)Irp
->Tail
.Overlay
.DriverContext
[0];
3041 Srb
= Irp
->Tail
.Overlay
.DriverContext
[3];
3042 if (!(Srb
->SrbFlags
& SRB_FLAGS_IS_ACTIVE
))
3044 BOOLEAN CompleteThisRequest
;
3045 LunExtension
= Irp
->Tail
.Overlay
.DriverContext
[2];
3046 IrpStack
= IoGetCurrentIrpStackLocation(Irp
);
3047 OriginalSrb
= IrpStack
->Parameters
.Scsi
.Srb
;
3049 if (Srb
->SrbStatus
== SRB_STATUS_BUSY
)
3051 CompleteThisRequest
= FALSE
;
3052 Irp
->Tail
.Overlay
.DriverContext
[3] = Srb
;
3054 SpiRemoveActiveIrp(DeviceExtension
, Irp
, PrevIrp
);
3055 SpiFreeSrbExtension(DeviceExtension
, OriginalSrb
);
3057 Srb
->OriginalRequest
= LunExtension
;
3058 Irp
->Tail
.Overlay
.DriverContext
[2] = 0;
3060 InsertHeadList(&DeviceExtension
->PendingIrpListHead
, (PLIST_ENTRY
)&Irp
->Tail
.Overlay
.DriverContext
[0]);
3061 DeviceExtension
->PendingIrpCount
++;
3062 LunExtension
->PendingIrpCount
++;
3067 if (OriginalSrb
!= Srb
)
3069 SENSE_DATA
* SenseInfoBuffer
;
3071 SenseInfoBuffer
= Srb
->DataBuffer
;
3073 DPRINT("Got sense data!\n");
3075 DPRINT("Valid: %x\n", SenseInfoBuffer
->Valid
);
3076 DPRINT("ErrorCode: %x\n", SenseInfoBuffer
->ErrorCode
);
3077 DPRINT("SenseKey: %x\n", SenseInfoBuffer
->SenseKey
);
3078 DPRINT("SenseCode: %x\n", SenseInfoBuffer
->AdditionalSenseCode
);
3080 /* Copy sense data */
3081 RtlCopyMemory(OriginalSrb
->SenseInfoBuffer
,
3083 sizeof(SENSE_DATA
));
3084 OriginalSrb
->SrbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
3085 OriginalSrb
->SrbExtension
= Srb
->SrbExtension
;
3087 CompleteThisRequest
= TRUE
;
3089 else if (SRB_STATUS(Srb
->SrbStatus
) != SRB_STATUS_SUCCESS
&&
3090 Srb
->ScsiStatus
== SCSISTAT_CHECK_CONDITION
&&
3091 Srb
->SenseInfoBuffer
!= NULL
&&
3092 Srb
->SenseInfoBufferLength
>= sizeof(SENSE_DATA
) &&
3093 !(Srb
->SrbStatus
& SRB_STATUS_AUTOSENSE_VALID
))
3095 DPRINT("SCSIOP_REQUEST_SENSE required!\n");
3097 Srb
= ScsiPortInitSenseRequestSrb(OriginalSrb
);
3101 CompleteThisRequest
= FALSE
;
3102 Irp
->Tail
.Overlay
.DriverContext
[3] = Srb
;
3103 SpiRemoveActiveIrp(DeviceExtension
, Irp
, PrevIrp
);
3104 SpiFreeSrbExtension(DeviceExtension
, OriginalSrb
);
3106 Srb
->OriginalRequest
= LunExtension
;
3107 Irp
->Tail
.Overlay
.DriverContext
[2] = 0;
3109 InsertHeadList(&DeviceExtension
->PendingIrpListHead
, (PLIST_ENTRY
)&Irp
->Tail
.Overlay
.DriverContext
[0]);
3110 DeviceExtension
->PendingIrpCount
++;
3111 LunExtension
->PendingIrpCount
++;
3117 CompleteThisRequest
= TRUE
;
3122 DPRINT("Complete Request\n");
3123 CompleteThisRequest
= TRUE
;
3125 if (CompleteThisRequest
)
3127 SpiRemoveActiveIrp(DeviceExtension
, Irp
, PrevIrp
);
3128 InsertHeadList(&CompleteIrpListHead
, (PLIST_ENTRY
)&Irp
->Tail
.Overlay
.DriverContext
[0]);
3129 SpiFreeSrbExtension(DeviceExtension
, OriginalSrb
);
3142 if (!IsListEmpty(&CompleteIrpListHead
))
3144 KeReleaseSpinLockFromDpcLevel(&DeviceExtension
->Lock
);
3145 while (!IsListEmpty(&CompleteIrpListHead
))
3147 ListEntry
= RemoveTailList(&CompleteIrpListHead
);
3148 Irp
= CONTAINING_RECORD(ListEntry
, IRP
, Tail
.Overlay
.DriverContext
[0]);
3149 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
3151 KeAcquireSpinLockAtDpcLevel(&DeviceExtension
->Lock
);
3153 if (DeviceExtension
->Flags
& (IRP_FLAG_NEXT
|IRP_FLAG_NEXT_LU
) &&
3154 (DeviceExtension
->SrbExtensionSize
== 0 || DeviceExtension
->CurrentSrbExtensions
< DeviceExtension
->MaxSrbExtensions
))
3156 BOOLEAN StartThisRequest
;
3157 ListEntry
= DeviceExtension
->PendingIrpListHead
.Flink
;
3158 while (ListEntry
!= &DeviceExtension
->PendingIrpListHead
)
3160 Irp
= CONTAINING_RECORD(ListEntry
, IRP
, Tail
.Overlay
.DriverContext
[0]);
3161 ListEntry
= ListEntry
->Flink
;
3162 Srb
= Irp
->Tail
.Overlay
.DriverContext
[3];
3163 LunExtension
= Srb
->OriginalRequest
;
3164 if (DeviceExtension
->SrbExtensionSize
> 0 &&
3165 DeviceExtension
->CurrentSrbExtensions
>= DeviceExtension
->MaxSrbExtensions
)
3169 if (LunExtension
->Flags
& IRP_FLAG_NEXT_LU
)
3171 StartThisRequest
= TRUE
;
3172 LunExtension
->Flags
&= ~IRP_FLAG_NEXT_LU
;
3173 DeviceExtension
->Flags
&= ~IRP_FLAG_NEXT_LU
;
3175 else if (DeviceExtension
->Flags
& IRP_FLAG_NEXT
&&
3176 LunExtension
->ActiveIrpCount
== 0)
3178 StartThisRequest
= TRUE
;
3179 DeviceExtension
->Flags
&= ~IRP_FLAG_NEXT
;
3183 StartThisRequest
= FALSE
;
3185 if (StartThisRequest
)
3187 LunExtension
->PendingIrpCount
--;
3188 DeviceExtension
->PendingIrpCount
--;
3189 Srb
->SrbFlags
|= SRB_FLAGS_IS_ACTIVE
;
3190 LunExtension
->ActiveIrpCount
++;
3191 DeviceExtension
->ActiveIrpCount
++;
3193 RemoveEntryList((PLIST_ENTRY
)&Irp
->Tail
.Overlay
.DriverContext
[0]);
3194 Irp
->Tail
.Overlay
.DriverContext
[2] = LunExtension
;
3195 Srb
->OriginalRequest
= Irp
;
3196 SpiAllocateSrbExtension(DeviceExtension
, Srb
);
3198 InsertHeadList(&NextIrpListHead
, (PLIST_ENTRY
)&Irp
->Tail
.Overlay
.DriverContext
[0]);
3203 if (!IsListEmpty(&NextIrpListHead
))
3205 while (!IsListEmpty(&NextIrpListHead
))
3207 ListEntry
= RemoveTailList(&NextIrpListHead
);
3208 Irp
= CONTAINING_RECORD(ListEntry
, IRP
, Tail
.Overlay
.DriverContext
[0]);
3209 KeReleaseSpinLockFromDpcLevel(&DeviceExtension
->Lock
);
3212 SpiStartIo(DeviceExtension
, Irp
);
3213 KeAcquireSpinLockAtDpcLevel(&DeviceExtension
->Lock
);
3217 if (!IsListEmpty(&DeviceExtension
->PendingIrpListHead
) &&
3218 DeviceExtension
->NextIrp
== NULL
&&
3219 (DeviceExtension
->SrbExtensionSize
== 0 || DeviceExtension
->CurrentSrbExtensions
< DeviceExtension
->MaxSrbExtensions
))
3221 ListEntry
= RemoveHeadList(&DeviceExtension
->PendingIrpListHead
);
3222 Irp
= CONTAINING_RECORD(ListEntry
, IRP
, Tail
.Overlay
.DriverContext
[0]);
3223 Srb
= Irp
->Tail
.Overlay
.DriverContext
[3];
3224 LunExtension
= Srb
->OriginalRequest
;
3225 Irp
->Tail
.Overlay
.DriverContext
[2] = LunExtension
;
3226 Srb
->OriginalRequest
= Irp
;
3228 LunExtension
->PendingIrpCount
--;
3229 DeviceExtension
->PendingIrpCount
--;
3230 Srb
->SrbFlags
|= SRB_FLAGS_IS_ACTIVE
;
3231 LunExtension
->ActiveIrpCount
++;
3232 DeviceExtension
->ActiveIrpCount
++;
3234 SpiAllocateSrbExtension(DeviceExtension
, Srb
);
3235 KeReleaseSpinLockFromDpcLevel(&DeviceExtension
->Lock
);
3237 /* Start this irp */
3238 SpiStartIo(DeviceExtension
, Irp
);
3239 KeAcquireSpinLockAtDpcLevel(&DeviceExtension
->Lock
);
3242 KeReleaseSpinLock(&DeviceExtension
->Lock
, oldIrql
);
3244 DPRINT("SpiProcessRequests() done\n");
3248 SpiStartIo(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
3251 PSCSI_PORT_LUN_EXTENSION LunExtension
;
3252 PSCSI_REQUEST_BLOCK Srb
;
3254 DPRINT("SpiStartIo() called!\n");
3256 assert(KeGetCurrentIrql() == DISPATCH_LEVEL
);
3258 Srb
= Irp
->Tail
.Overlay
.DriverContext
[3];
3259 LunExtension
= Irp
->Tail
.Overlay
.DriverContext
[2];
3261 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
3262 Irp
->IoStatus
.Information
= Srb
->DataTransferLength
;
3264 SpiAddActiveIrp(DeviceExtension
, Irp
);
3266 if (!KeSynchronizeExecution(DeviceExtension
->Interrupt
,
3267 ScsiPortStartPacket
,
3270 DPRINT1("Synchronization failed!\n");
3271 DPRINT1("Irp %x, Srb->Function %02x, Srb->Cdb[0] %02x, Srb->SrbStatus %02x\n", Irp
, Srb
->Function
, Srb
->Cdb
[0], Srb
->SrbStatus
);
3272 ScsiPortNotification(RequestComplete
,
3273 &DeviceExtension
->MiniPortDeviceExtension
,
3277 DPRINT("SpiStartIo() done\n");