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 <ntos/minmax.h>
36 #include <rosrtl/string.h>
41 #include "scsiport_int.h"
43 /* TYPES *********************************************************************/
45 #define IRP_FLAG_COMPLETE 0x00000001
46 #define IRP_FLAG_NEXT 0x00000002
47 #define IRP_FLAG_NEXT_LU 0x00000004
49 /* GLOBALS *******************************************************************/
51 static ULONG InternalDebugLevel
= 0;
54 SpiProcessRequests(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
58 SpiStartIo(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
62 SpiGetPciConfigData (IN
struct _HW_INITIALIZATION_DATA
*HwInitializationData
,
63 IN OUT PPORT_CONFIGURATION_INFORMATION PortConfig
,
65 IN OUT PPCI_SLOT_NUMBER NextSlotNumber
);
67 static NTSTATUS STDCALL
68 ScsiPortCreateClose(IN PDEVICE_OBJECT DeviceObject
,
71 static NTSTATUS STDCALL
72 ScsiPortDispatchScsi(IN PDEVICE_OBJECT DeviceObject
,
75 static NTSTATUS STDCALL
76 ScsiPortDeviceControl(IN PDEVICE_OBJECT DeviceObject
,
79 static BOOLEAN STDCALL
80 ScsiPortStartPacket(IN OUT PVOID Context
);
83 static PSCSI_PORT_LUN_EXTENSION
84 SpiAllocateLunExtension (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
90 SpiRemoveLunExtension (IN PSCSI_PORT_LUN_EXTENSION LunExtension
);
92 static PSCSI_PORT_LUN_EXTENSION
93 SpiGetLunExtension (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
99 SpiSendInquiry (IN PDEVICE_OBJECT DeviceObject
,
100 IN OUT PSCSI_REQUEST_BLOCK Srb
,
101 IN OUT PIO_STATUS_BLOCK IoStatusBlock
,
102 IN OUT PKEVENT Event
);
105 SpiScanAdapter (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
);
108 SpiGetInquiryData (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
109 OUT PSCSI_ADAPTER_BUS_INFO AdapterBusInfo
);
111 static BOOLEAN STDCALL
112 ScsiPortIsr(IN PKINTERRUPT Interrupt
,
113 IN PVOID ServiceContext
);
116 ScsiPortDpc(IN PKDPC Dpc
,
117 IN PDEVICE_OBJECT DpcDeviceObject
,
119 IN PVOID DpcContext
);
122 ScsiPortIoTimer(PDEVICE_OBJECT DeviceObject
,
125 static PSCSI_REQUEST_BLOCK
126 ScsiPortInitSenseRequestSrb(PSCSI_REQUEST_BLOCK OriginalSrb
);
129 SpiBuildDeviceMap (PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
130 PUNICODE_STRING RegistryPath
);
133 SpiAllocateSrbExtension(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
134 PSCSI_REQUEST_BLOCK Srb
);
137 SpiFreeSrbExtension(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
138 PSCSI_REQUEST_BLOCK Srb
);
141 /* FUNCTIONS *****************************************************************/
143 /**********************************************************************
148 * This function initializes the driver.
155 * System allocated Driver Object for this driver.
158 * Name of registry driver service key.
165 DriverEntry(IN PDRIVER_OBJECT DriverObject
,
166 IN PUNICODE_STRING RegistryPath
)
168 DPRINT("ScsiPort Driver %s\n", VERSION
);
169 return(STATUS_SUCCESS
);
173 /**********************************************************************
178 * Prints debugging messages.
185 * Debug level of the given message.
188 * Pointer to printf()-compatible format string.
191 Additional output data (see printf()).
200 ScsiDebugPrint(IN ULONG DebugPrintLevel
,
201 IN PCHAR DebugMessage
,
207 if (DebugPrintLevel
>= InternalDebugLevel
)
210 va_start(ap
, DebugMessage
);
211 vsprintf(Buffer
, DebugMessage
, ap
);
222 ScsiPortCompleteRequest(IN PVOID HwDeviceExtension
,
228 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
229 PSCSI_PORT_LUN_EXTENSION LunExtension
;
232 PSCSI_REQUEST_BLOCK Srb
;
234 DPRINT("ScsiPortCompleteRequest(HwDeviceExtension %x, PathId %d, TargetId %d, Lun %d, SrbStatus %x)\n",
235 HwDeviceExtension
, PathId
, TargetId
, Lun
, SrbStatus
);
237 DeviceExtension
= CONTAINING_RECORD(HwDeviceExtension
,
238 SCSI_PORT_DEVICE_EXTENSION
,
239 MiniPortDeviceExtension
);
241 Entry
= DeviceExtension
->LunExtensionListHead
.Flink
;
242 while (Entry
!= &DeviceExtension
->LunExtensionListHead
)
244 LunExtension
= CONTAINING_RECORD(Entry
,
245 SCSI_PORT_LUN_EXTENSION
,
250 if (PathId
== (UCHAR
)SP_UNTAGGED
||
251 (PathId
== LunExtension
->PathId
&& TargetId
== (UCHAR
)SP_UNTAGGED
) ||
252 (PathId
== LunExtension
->PathId
&& TargetId
== LunExtension
->TargetId
&& Lun
== (UCHAR
)SP_UNTAGGED
) ||
253 (PathId
== LunExtension
->PathId
&& TargetId
== LunExtension
->TargetId
&& Lun
== LunExtension
->Lun
))
255 Irp
= LunExtension
->NextIrp
;
258 Srb
= (PSCSI_REQUEST_BLOCK
)Irp
->Tail
.Overlay
.DriverContext
[3];
259 if (Srb
->SrbFlags
& SRB_FLAGS_IS_ACTIVE
)
261 Srb
->SrbStatus
= SrbStatus
;
262 ScsiPortNotification(RequestComplete
,
266 Irp
= Irp
->Tail
.Overlay
.DriverContext
[1];
269 Entry
= Entry
->Flink
;
278 ScsiPortConvertPhysicalAddressToUlong(IN SCSI_PHYSICAL_ADDRESS Address
)
280 DPRINT("ScsiPortConvertPhysicalAddressToUlong()\n");
281 return(Address
.u
.LowPart
);
289 ScsiPortFlushDma(IN PVOID HwDeviceExtension
)
291 DPRINT("ScsiPortFlushDma()\n");
300 ScsiPortFreeDeviceBase(IN PVOID HwDeviceExtension
,
301 IN PVOID MappedAddress
)
303 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
304 PSCSI_PORT_DEVICE_BASE DeviceBase
;
307 DPRINT("ScsiPortFreeDeviceBase() called\n");
309 DeviceExtension
= CONTAINING_RECORD(HwDeviceExtension
,
310 SCSI_PORT_DEVICE_EXTENSION
,
311 MiniPortDeviceExtension
);
312 if (IsListEmpty(&DeviceExtension
->DeviceBaseListHead
))
315 Entry
= DeviceExtension
->DeviceBaseListHead
.Flink
;
316 while (Entry
!= &DeviceExtension
->DeviceBaseListHead
)
318 DeviceBase
= CONTAINING_RECORD(Entry
,
319 SCSI_PORT_DEVICE_BASE
,
321 if (DeviceBase
->MappedAddress
== MappedAddress
)
323 MmUnmapIoSpace(DeviceBase
->MappedAddress
,
324 DeviceBase
->NumberOfBytes
);
325 RemoveEntryList(Entry
);
326 ExFreePool(DeviceBase
);
331 Entry
= Entry
->Flink
;
340 ScsiPortGetBusData(IN PVOID DeviceExtension
,
341 IN ULONG BusDataType
,
342 IN ULONG SystemIoBusNumber
,
347 return(HalGetBusData(BusDataType
,
359 ScsiPortGetDeviceBase(IN PVOID HwDeviceExtension
,
360 IN INTERFACE_TYPE BusType
,
361 IN ULONG SystemIoBusNumber
,
362 IN SCSI_PHYSICAL_ADDRESS IoAddress
,
363 IN ULONG NumberOfBytes
,
364 IN BOOLEAN InIoSpace
)
366 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
367 PHYSICAL_ADDRESS TranslatedAddress
;
368 PSCSI_PORT_DEVICE_BASE DeviceBase
;
372 DPRINT ("ScsiPortGetDeviceBase() called\n");
374 AddressSpace
= (ULONG
)InIoSpace
;
375 if (HalTranslateBusAddress(BusType
,
379 &TranslatedAddress
) == FALSE
)
383 if (AddressSpace
!= 0)
384 return((PVOID
)TranslatedAddress
.u
.LowPart
);
386 MappedAddress
= MmMapIoSpace(TranslatedAddress
,
390 DeviceBase
= ExAllocatePool(NonPagedPool
,
391 sizeof(SCSI_PORT_DEVICE_BASE
));
392 if (DeviceBase
== NULL
)
393 return(MappedAddress
);
395 DeviceBase
->MappedAddress
= MappedAddress
;
396 DeviceBase
->NumberOfBytes
= NumberOfBytes
;
397 DeviceBase
->IoAddress
= IoAddress
;
398 DeviceBase
->SystemIoBusNumber
= SystemIoBusNumber
;
400 DeviceExtension
= CONTAINING_RECORD(HwDeviceExtension
,
401 SCSI_PORT_DEVICE_EXTENSION
,
402 MiniPortDeviceExtension
);
404 InsertHeadList(&DeviceExtension
->DeviceBaseListHead
,
407 return(MappedAddress
);
415 ScsiPortGetLogicalUnit(IN PVOID HwDeviceExtension
,
420 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
421 PSCSI_PORT_LUN_EXTENSION LunExtension
;
424 DPRINT("ScsiPortGetLogicalUnit() called\n");
426 DeviceExtension
= CONTAINING_RECORD(HwDeviceExtension
,
427 SCSI_PORT_DEVICE_EXTENSION
,
428 MiniPortDeviceExtension
);
429 if (IsListEmpty(&DeviceExtension
->LunExtensionListHead
))
432 Entry
= DeviceExtension
->LunExtensionListHead
.Flink
;
433 while (Entry
!= &DeviceExtension
->LunExtensionListHead
)
435 LunExtension
= CONTAINING_RECORD(Entry
,
436 SCSI_PORT_LUN_EXTENSION
,
438 if (LunExtension
->PathId
== PathId
&&
439 LunExtension
->TargetId
== TargetId
&&
440 LunExtension
->Lun
== Lun
)
442 return (PVOID
)&LunExtension
->MiniportLunExtension
;
445 Entry
= Entry
->Flink
;
455 SCSI_PHYSICAL_ADDRESS STDCALL
456 ScsiPortGetPhysicalAddress(IN PVOID HwDeviceExtension
,
457 IN PSCSI_REQUEST_BLOCK Srb OPTIONAL
,
458 IN PVOID VirtualAddress
,
461 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
462 SCSI_PHYSICAL_ADDRESS PhysicalAddress
;
463 SCSI_PHYSICAL_ADDRESS NextPhysicalAddress
;
464 ULONG BufferLength
= 0;
468 DPRINT("ScsiPortGetPhysicalAddress(%p %p %p %p)\n",
469 HwDeviceExtension
, Srb
, VirtualAddress
, Length
);
471 DeviceExtension
= CONTAINING_RECORD(HwDeviceExtension
,
472 SCSI_PORT_DEVICE_EXTENSION
,
473 MiniPortDeviceExtension
);
481 EndAddress
= DeviceExtension
->VirtualAddress
+ DeviceExtension
->CommonBufferLength
;
482 if (VirtualAddress
>= DeviceExtension
->VirtualAddress
&& VirtualAddress
< EndAddress
)
484 Offset
= (ULONG_PTR
)VirtualAddress
- (ULONG_PTR
)DeviceExtension
->VirtualAddress
;
485 PhysicalAddress
.QuadPart
= DeviceExtension
->PhysicalAddress
.QuadPart
+ Offset
;
486 BufferLength
= (ULONG_PTR
)EndAddress
- (ULONG_PTR
)VirtualAddress
;
491 * The given virtual address is not within the range
492 * of the drivers uncached extension or srb extension.
496 * Check if the address is a sense info buffer of an active srb.
498 PhysicalAddress
= MmGetPhysicalAddress(VirtualAddress
);
499 if (PhysicalAddress
.QuadPart
== 0LL)
502 return PhysicalAddress
;
504 BufferLength
= PAGE_SIZE
- PhysicalAddress
.u
.LowPart
% PAGE_SIZE
;
509 EndAddress
= Srb
->DataBuffer
+ Srb
->DataTransferLength
;
510 if (VirtualAddress
== NULL
)
512 VirtualAddress
= Srb
->DataBuffer
;
514 else if (VirtualAddress
< Srb
->DataBuffer
|| VirtualAddress
>= EndAddress
)
516 EndAddress
= Srb
->SenseInfoBuffer
+ Srb
->SenseInfoBufferLength
;
517 if (VirtualAddress
< Srb
->SenseInfoBuffer
|| VirtualAddress
>= EndAddress
)
519 PhysicalAddress
.QuadPart
= 0LL;
521 return PhysicalAddress
;
525 PhysicalAddress
= MmGetPhysicalAddress(VirtualAddress
);
526 if (PhysicalAddress
.QuadPart
== 0LL)
529 return PhysicalAddress
;
532 BufferLength
= PAGE_SIZE
- (ULONG_PTR
)VirtualAddress
% PAGE_SIZE
;
533 while (VirtualAddress
+ BufferLength
< EndAddress
)
535 NextPhysicalAddress
= MmGetPhysicalAddress(VirtualAddress
+ BufferLength
);
536 if (PhysicalAddress
.QuadPart
+ BufferLength
!= NextPhysicalAddress
.QuadPart
)
540 BufferLength
+= PAGE_SIZE
;
542 if (VirtualAddress
+ BufferLength
>= EndAddress
)
544 BufferLength
= EndAddress
- VirtualAddress
;
549 *Length
= BufferLength
;
551 DPRINT("Address %I64x, Length %d\n", PhysicalAddress
.QuadPart
, BufferLength
);
552 return PhysicalAddress
;
559 PSCSI_REQUEST_BLOCK STDCALL
560 ScsiPortGetSrb(IN PVOID HwDeviceExtension
,
566 DPRINT1("ScsiPortGetSrb() unimplemented\n");
576 ScsiPortGetUncachedExtension(IN PVOID HwDeviceExtension
,
577 IN PPORT_CONFIGURATION_INFORMATION ConfigInfo
,
578 IN ULONG NumberOfBytes
)
580 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
581 DEVICE_DESCRIPTION DeviceDescription
;
583 DPRINT("ScsiPortGetUncachedExtension(%p %p %lu)\n",
584 HwDeviceExtension
, ConfigInfo
, NumberOfBytes
);
586 DeviceExtension
= CONTAINING_RECORD(HwDeviceExtension
,
587 SCSI_PORT_DEVICE_EXTENSION
,
588 MiniPortDeviceExtension
);
590 /* Check for allocated common DMA buffer */
591 if (DeviceExtension
->VirtualAddress
!= NULL
)
593 DPRINT1("The HBA has already got a common DMA buffer!\n");
597 /* Check for DMA adapter object */
598 if (DeviceExtension
->AdapterObject
== NULL
)
600 /* Initialize DMA adapter description */
601 RtlZeroMemory(&DeviceDescription
,
602 sizeof(DEVICE_DESCRIPTION
));
603 DeviceDescription
.Version
= DEVICE_DESCRIPTION_VERSION
;
604 DeviceDescription
.Master
= ConfigInfo
->Master
;
605 DeviceDescription
.ScatterGather
= ConfigInfo
->ScatterGather
;
606 DeviceDescription
.DemandMode
= ConfigInfo
->DemandMode
;
607 DeviceDescription
.Dma32BitAddresses
= ConfigInfo
->Dma32BitAddresses
;
608 DeviceDescription
.BusNumber
= ConfigInfo
->SystemIoBusNumber
;
609 DeviceDescription
.DmaChannel
= ConfigInfo
->DmaChannel
;
610 DeviceDescription
.InterfaceType
= ConfigInfo
->AdapterInterfaceType
;
611 DeviceDescription
.DmaWidth
= ConfigInfo
->DmaWidth
;
612 DeviceDescription
.DmaSpeed
= ConfigInfo
->DmaSpeed
;
613 DeviceDescription
.MaximumLength
= ConfigInfo
->MaximumTransferLength
;
614 DeviceDescription
.DmaPort
= ConfigInfo
->DmaPort
;
616 /* Get a DMA adapter object */
617 DeviceExtension
->AdapterObject
= HalGetAdapter(&DeviceDescription
,
618 &DeviceExtension
->MapRegisterCount
);
619 if (DeviceExtension
->AdapterObject
== NULL
)
621 DPRINT1("HalGetAdapter() failed\n");
625 if (DeviceExtension
->SrbExtensionSize
> 0)
628 DeviceExtension
->CurrentSrbExtensions
= 0;
629 if (DeviceExtension
->PortConfig
->MultipleRequestPerLu
)
631 DeviceExtension
->MaxSrbExtensions
= 1024;
635 DeviceExtension
->MaxSrbExtensions
= 32;
637 Buffer
= ExAllocatePool(NonPagedPool
, ROUND_UP(DeviceExtension
->MaxSrbExtensions
/ 8, sizeof(ULONG
)));
643 RtlInitializeBitMap(&DeviceExtension
->SrbExtensionAllocMap
, Buffer
, DeviceExtension
->MaxSrbExtensions
);
644 RtlClearAllBits(&DeviceExtension
->SrbExtensionAllocMap
);
647 /* Allocate a common DMA buffer */
648 DeviceExtension
->CommonBufferLength
=
649 NumberOfBytes
+ PAGE_ROUND_UP(DeviceExtension
->SrbExtensionSize
* DeviceExtension
->MaxSrbExtensions
);
650 DeviceExtension
->VirtualAddress
=
651 HalAllocateCommonBuffer(DeviceExtension
->AdapterObject
,
652 DeviceExtension
->CommonBufferLength
,
653 &DeviceExtension
->PhysicalAddress
,
655 if (DeviceExtension
->VirtualAddress
== NULL
)
657 DPRINT1("HalAllocateCommonBuffer() failed!\n");
658 DeviceExtension
->CommonBufferLength
= 0;
662 return (PVOID
)((ULONG_PTR
)DeviceExtension
->VirtualAddress
+
663 PAGE_ROUND_UP(DeviceExtension
->SrbExtensionSize
* DeviceExtension
->MaxSrbExtensions
));
671 ScsiPortGetVirtualAddress(IN PVOID HwDeviceExtension
,
672 IN SCSI_PHYSICAL_ADDRESS PhysicalAddress
)
674 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
677 DPRINT("ScsiPortGetVirtualAddress(%p %I64x)\n",
678 HwDeviceExtension
, PhysicalAddress
.QuadPart
);
680 DeviceExtension
= CONTAINING_RECORD(HwDeviceExtension
,
681 SCSI_PORT_DEVICE_EXTENSION
,
682 MiniPortDeviceExtension
);
684 if (DeviceExtension
->PhysicalAddress
.QuadPart
> PhysicalAddress
.QuadPart
)
687 Offset
= (ULONG
)(PhysicalAddress
.QuadPart
- DeviceExtension
->PhysicalAddress
.QuadPart
);
688 if (Offset
>= DeviceExtension
->CommonBufferLength
)
691 return (PVOID
)((ULONG_PTR
)DeviceExtension
->VirtualAddress
+ Offset
);
695 /**********************************************************************
700 * Initializes SCSI port driver specific data.
707 * Pointer to the miniport driver's driver object.
710 * Pointer to the miniport driver's registry path.
712 * HwInitializationData
713 * Pointer to port driver specific configuration data.
716 Miniport driver specific context.
725 ScsiPortInitialize(IN PVOID Argument1
,
727 IN
struct _HW_INITIALIZATION_DATA
*HwInitializationData
,
730 PDRIVER_OBJECT DriverObject
= (PDRIVER_OBJECT
)Argument1
;
731 // PUNICODE_STRING RegistryPath = (PUNICODE_STRING)Argument2;
732 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
733 PCONFIGURATION_INFORMATION SystemConfig
;
734 PPORT_CONFIGURATION_INFORMATION PortConfig
;
735 ULONG DeviceExtensionSize
;
736 ULONG PortConfigSize
;
738 BOOLEAN DeviceFound
= FALSE
;
744 PCI_SLOT_NUMBER SlotNumber
;
746 PDEVICE_OBJECT PortDeviceObject
;
747 WCHAR NameBuffer
[80];
748 UNICODE_STRING DeviceName
;
749 WCHAR DosNameBuffer
[80];
750 UNICODE_STRING DosDeviceName
;
751 PIO_SCSI_CAPABILITIES PortCapabilities
;
757 DPRINT ("ScsiPortInitialize() called!\n");
759 DPRINT1("HwInitializationDataSize: %d\n", HwInitializationData
->HwInitializationDataSize
);
760 DPRINT1("AdapterInterfaceType: %d\n", HwInitializationData
->AdapterInterfaceType
);
761 DPRINT1("HwInitialize: %x\n", HwInitializationData
->HwInitialize
);
762 DPRINT1("HwStartIo: %x\n", HwInitializationData
->HwStartIo
);
763 DPRINT1("HwInterrupt: %x\n", HwInitializationData
->HwInterrupt
);
764 DPRINT1("HwFindAdapter: %x\n", HwInitializationData
->HwFindAdapter
);
765 DPRINT1("HwResetBus: %x\n", HwInitializationData
->HwResetBus
);
766 DPRINT1("HwDmaStarted: %x\n", HwInitializationData
->HwDmaStarted
);
767 DPRINT1("HwAdapterState: %x\n", HwInitializationData
->HwAdapterState
);
768 DPRINT1("DeviceExtensionSize: %d\n", HwInitializationData
->DeviceExtensionSize
);
769 DPRINT1("SpecificLuExtensionSize: %d\n", HwInitializationData
->SpecificLuExtensionSize
);
770 DPRINT1("SrbExtensionSize: %d\n", HwInitializationData
->SrbExtensionSize
);
771 DPRINT1("NumberOfAccessRanges: %d\n", HwInitializationData
->NumberOfAccessRanges
);
772 DPRINT1("Reserved: %x\n", HwInitializationData
->Reserved
);
773 DPRINT1("MapBuffers: %d\n", HwInitializationData
->MapBuffers
);
774 DPRINT1("NeedPhysicalAddresses: %d\n", HwInitializationData
->NeedPhysicalAddresses
);
775 DPRINT1("TaggedQueueing: %d\n", HwInitializationData
->TaggedQueueing
);
776 DPRINT1("AutoRequestSense: %d\n", HwInitializationData
->AutoRequestSense
);
777 DPRINT1("MultipleRequestPerLu: %d\n", HwInitializationData
->MultipleRequestPerLu
);
778 DPRINT1("ReceiveEvent: %d\n", HwInitializationData
->ReceiveEvent
);
779 DPRINT1("VendorIdLength: %d\n", HwInitializationData
->VendorIdLength
);
780 DPRINT1("VendorId: %x\n", HwInitializationData
->VendorId
);
781 DPRINT1("ReservedUshort: %d\n", HwInitializationData
->ReservedUshort
);
782 DPRINT1("DeviceIdLength: %d\n", HwInitializationData
->DeviceIdLength
);
783 DPRINT1("DeviceId: %x\n", HwInitializationData
->DeviceId
);
785 if ((HwInitializationData
->HwInitialize
== NULL
) ||
786 (HwInitializationData
->HwStartIo
== NULL
) ||
787 (HwInitializationData
->HwInterrupt
== NULL
) ||
788 (HwInitializationData
->HwFindAdapter
== NULL
) ||
789 (HwInitializationData
->HwResetBus
== NULL
))
790 return(STATUS_INVALID_PARAMETER
);
792 DriverObject
->DriverStartIo
= NULL
;
793 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = ScsiPortCreateClose
;
794 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = ScsiPortCreateClose
;
795 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = ScsiPortDeviceControl
;
796 DriverObject
->MajorFunction
[IRP_MJ_SCSI
] = ScsiPortDispatchScsi
;
798 SystemConfig
= IoGetConfigurationInformation();
800 DeviceExtensionSize
= sizeof(SCSI_PORT_DEVICE_EXTENSION
) +
801 HwInitializationData
->DeviceExtensionSize
;
802 PortConfigSize
= sizeof(PORT_CONFIGURATION_INFORMATION
) +
803 HwInitializationData
->NumberOfAccessRanges
* sizeof(ACCESS_RANGE
);
806 MaxBus
= (HwInitializationData
->AdapterInterfaceType
== PCIBus
) ? 8 : 1;
807 DPRINT("MaxBus: %lu\n", MaxBus
);
809 PortDeviceObject
= NULL
;
811 SlotNumber
.u
.AsULONG
= 0;
814 /* Create a unicode device name */
815 swprintf (NameBuffer
,
816 L
"\\Device\\ScsiPort%lu",
817 SystemConfig
->ScsiPortCount
);
818 RtlInitUnicodeString (&DeviceName
,
821 DPRINT("Creating device: %wZ\n", &DeviceName
);
823 /* Create the port device */
824 Status
= IoCreateDevice (DriverObject
,
827 FILE_DEVICE_CONTROLLER
,
831 if (!NT_SUCCESS(Status
))
833 DbgPrint ("IoCreateDevice call failed! (Status 0x%lX)\n", Status
);
834 PortDeviceObject
= NULL
;
838 DPRINT ("Created device: %wZ (%p)\n", &DeviceName
, PortDeviceObject
);
840 /* Set the buffering strategy here... */
841 PortDeviceObject
->Flags
|= DO_DIRECT_IO
;
842 PortDeviceObject
->AlignmentRequirement
= FILE_WORD_ALIGNMENT
;
844 DeviceExtension
= PortDeviceObject
->DeviceExtension
;
845 RtlZeroMemory(DeviceExtension
, DeviceExtensionSize
);
846 DeviceExtension
->Length
= DeviceExtensionSize
;
847 DeviceExtension
->DeviceObject
= PortDeviceObject
;
848 DeviceExtension
->PortNumber
= SystemConfig
->ScsiPortCount
;
850 DeviceExtension
->MiniPortExtensionSize
= HwInitializationData
->DeviceExtensionSize
;
851 DeviceExtension
->LunExtensionSize
= HwInitializationData
->SpecificLuExtensionSize
;
852 DeviceExtension
->SrbExtensionSize
= HwInitializationData
->SrbExtensionSize
;
853 DeviceExtension
->HwStartIo
= HwInitializationData
->HwStartIo
;
854 DeviceExtension
->HwInterrupt
= HwInitializationData
->HwInterrupt
;
856 DeviceExtension
->AdapterObject
= NULL
;
857 DeviceExtension
->MapRegisterCount
= 0;
858 DeviceExtension
->PhysicalAddress
.QuadPart
= 0ULL;
859 DeviceExtension
->VirtualAddress
= NULL
;
860 DeviceExtension
->CommonBufferLength
= 0;
862 /* Initialize the device base list */
863 InitializeListHead (&DeviceExtension
->DeviceBaseListHead
);
865 /* Initialize the irp lists */
866 InitializeListHead (&DeviceExtension
->PendingIrpListHead
);
867 DeviceExtension
->NextIrp
= NULL
;
868 DeviceExtension
->PendingIrpCount
= 0;
869 DeviceExtension
->ActiveIrpCount
= 0;
871 /* Initialize LUN-Extension list */
872 InitializeListHead (&DeviceExtension
->LunExtensionListHead
);
874 /* Initialize the spin lock in the controller extension */
875 KeInitializeSpinLock (&DeviceExtension
->Lock
);
877 /* Initialize the DPC object */
878 IoInitializeDpcRequest (PortDeviceObject
,
881 /* Initialize the device timer */
882 DeviceExtension
->TimerState
= IDETimerIdle
;
883 DeviceExtension
->TimerCount
= 0;
884 IoInitializeTimer (PortDeviceObject
,
888 /* Allocate and initialize port configuration info */
889 DeviceExtension
->PortConfig
= ExAllocatePool (NonPagedPool
,
891 if (DeviceExtension
->PortConfig
== NULL
)
893 Status
= STATUS_INSUFFICIENT_RESOURCES
;
896 RtlZeroMemory (DeviceExtension
->PortConfig
,
899 PortConfig
= DeviceExtension
->PortConfig
;
900 PortConfig
->Length
= sizeof(PORT_CONFIGURATION_INFORMATION
);
901 PortConfig
->SystemIoBusNumber
= BusNumber
;
902 PortConfig
->AdapterInterfaceType
= HwInitializationData
->AdapterInterfaceType
;
903 PortConfig
->InterruptMode
=
904 (PortConfig
->AdapterInterfaceType
== PCIBus
) ? LevelSensitive
: Latched
;
905 PortConfig
->MaximumTransferLength
= SP_UNINITIALIZED_VALUE
;
906 PortConfig
->NumberOfPhysicalBreaks
= SP_UNINITIALIZED_VALUE
;
907 PortConfig
->DmaChannel
= SP_UNINITIALIZED_VALUE
;
908 PortConfig
->DmaPort
= SP_UNINITIALIZED_VALUE
;
909 PortConfig
->DmaWidth
= 0;
910 PortConfig
->DmaSpeed
= Compatible
;
911 PortConfig
->AlignmentMask
= 0;
912 PortConfig
->NumberOfAccessRanges
= HwInitializationData
->NumberOfAccessRanges
;
913 PortConfig
->NumberOfBuses
= 0;
915 for (i
= 0; i
< SCSI_MAXIMUM_BUSES
; i
++)
916 PortConfig
->InitiatorBusId
[i
] = 255;
918 PortConfig
->ScatterGather
= FALSE
;
919 PortConfig
->Master
= FALSE
;
920 PortConfig
->CachesData
= FALSE
;
921 PortConfig
->AdapterScansDown
= FALSE
;
922 PortConfig
->AtdiskPrimaryClaimed
= SystemConfig
->AtDiskPrimaryAddressClaimed
;
923 PortConfig
->AtdiskSecondaryClaimed
= SystemConfig
->AtDiskSecondaryAddressClaimed
;
924 PortConfig
->Dma32BitAddresses
= FALSE
;
925 PortConfig
->DemandMode
= FALSE
;
926 PortConfig
->MapBuffers
= HwInitializationData
->MapBuffers
;
927 PortConfig
->NeedPhysicalAddresses
= HwInitializationData
->NeedPhysicalAddresses
;
928 PortConfig
->TaggedQueuing
= HwInitializationData
->TaggedQueueing
;
929 PortConfig
->AutoRequestSense
= HwInitializationData
->AutoRequestSense
;
930 PortConfig
->MultipleRequestPerLu
= HwInitializationData
->MultipleRequestPerLu
;
931 PortConfig
->ReceiveEvent
= HwInitializationData
->ReceiveEvent
;
932 PortConfig
->RealModeInitialized
= FALSE
;
933 PortConfig
->BufferAccessScsiPortControlled
= FALSE
;
934 PortConfig
->MaximumNumberOfTargets
= SCSI_MAXIMUM_TARGETS
;
935 // PortConfig->MaximumNumberOfLogicalUnits = SCSI_MAXIMUM_LOGICAL_UNITS;
937 PortConfig
->SrbExtensionSize
= HwInitializationData
->SrbExtensionSize
;
938 PortConfig
->SpecificLuExtensionSize
= HwInitializationData
->SpecificLuExtensionSize
;
940 PortConfig
->AccessRanges
= (PACCESS_RANGE
)(PortConfig
+ 1);
942 /* Search for matching PCI device */
943 if ((HwInitializationData
->AdapterInterfaceType
== PCIBus
) &&
944 (HwInitializationData
->VendorIdLength
> 0) &&
945 (HwInitializationData
->VendorId
!= NULL
) &&
946 (HwInitializationData
->DeviceIdLength
> 0) &&
947 (HwInitializationData
->DeviceId
!= NULL
))
949 /* Get PCI device data */
950 DPRINT("VendorId '%.*s' DeviceId '%.*s'\n",
951 HwInitializationData
->VendorIdLength
,
952 HwInitializationData
->VendorId
,
953 HwInitializationData
->DeviceIdLength
,
954 HwInitializationData
->DeviceId
);
956 if (!SpiGetPciConfigData (HwInitializationData
,
961 Status
= STATUS_UNSUCCESSFUL
;
966 /* Note: HwFindAdapter is called once for each bus */
968 DPRINT("Calling HwFindAdapter() for Bus %lu\n", PortConfig
->SystemIoBusNumber
);
969 Result
= (HwInitializationData
->HwFindAdapter
)(&DeviceExtension
->MiniPortDeviceExtension
,
971 0, /* BusInformation */
972 "", /* ArgumentString */
975 DPRINT("HwFindAdapter() Result: %lu Again: %s\n",
976 Result
, (Again
) ? "True" : "False");
978 if (Result
== SP_RETURN_FOUND
)
980 DPRINT("ScsiPortInitialize(): Found HBA! (%x)\n", PortConfig
->BusInterruptVector
);
983 DPRINT1("SystemIoBusNumber: %x\n", PortConfig
->SystemIoBusNumber
);
984 DPRINT1("AdapterInterfaceType: %x\n", PortConfig
->AdapterInterfaceType
);
985 DPRINT1("BusInterruptLevel: %x\n", PortConfig
->BusInterruptLevel
);
986 DPRINT1("BusInterruptVector: %x\n", PortConfig
->BusInterruptVector
);
987 DPRINT1("InterruptMode: %x\n", PortConfig
->InterruptMode
);
988 DPRINT1("MaximumTransferLength: %x\n", PortConfig
->MaximumTransferLength
);
989 DPRINT1("NumberOfPhysicalBreaks: %x\n", PortConfig
->NumberOfPhysicalBreaks
);
990 DPRINT1("DmaChannel: %x\n", PortConfig
->DmaChannel
);
991 DPRINT1("DmaPort: %d\n", PortConfig
->DmaPort
);
992 DPRINT1("DmaWidth: %d\n", PortConfig
->DmaWidth
);
993 DPRINT1("DmaSpeed: %d\n", PortConfig
->DmaSpeed
);
994 DPRINT1("AlignmentMask: %d\n", PortConfig
->AlignmentMask
);
995 DPRINT1("NumberOfAccessRanges: %d\n", PortConfig
->NumberOfAccessRanges
);
996 DPRINT1("NumberOfBuses: %d\n", PortConfig
->NumberOfBuses
);
997 DPRINT1("ScatterGather: %d\n", PortConfig
->ScatterGather
);
998 DPRINT1("Master: %d\n", PortConfig
->Master
);
999 DPRINT1("CachesData: %d\n", PortConfig
->CachesData
);
1000 DPRINT1("AdapterScansDown: %d\n", PortConfig
->AdapterScansDown
);
1001 DPRINT1("AtdiskPrimaryClaimed: %d\n", PortConfig
->AtdiskPrimaryClaimed
);
1002 DPRINT1("AtdiskSecondaryClaimed: %d\n", PortConfig
->AtdiskSecondaryClaimed
);
1003 DPRINT1("Dma32BitAddresses: %d\n", PortConfig
->Dma32BitAddresses
);
1004 DPRINT1("DemandMode: %d\n", PortConfig
->DemandMode
);
1005 DPRINT1("MapBuffers: %d\n", PortConfig
->MapBuffers
);
1006 DPRINT1("NeedPhysicalAddresses: %d\n", PortConfig
->NeedPhysicalAddresses
);
1007 DPRINT1("TaggedQueuing: %d\n", PortConfig
->TaggedQueuing
);
1008 DPRINT1("AutoRequestSense: %d\n", PortConfig
->AutoRequestSense
);
1009 DPRINT1("MultipleRequestPerLu: %d\n", PortConfig
->MultipleRequestPerLu
);
1010 DPRINT1("ReceiveEvent: %d\n", PortConfig
->ReceiveEvent
);
1011 DPRINT1("RealModeInitialized: %d\n", PortConfig
->RealModeInitialized
);
1012 DPRINT1("BufferAccessScsiPortControlled: %d\n", PortConfig
->BufferAccessScsiPortControlled
);
1013 DPRINT1("MaximumNumberOfTargets: %d\n", PortConfig
->MaximumNumberOfTargets
);
1014 DPRINT1("SlotNumber: %d\n", PortConfig
->SlotNumber
);
1015 DPRINT1("BusInterruptLevel2: %x\n", PortConfig
->BusInterruptLevel2
);
1016 DPRINT1("BusInterruptVector2: %x\n", PortConfig
->BusInterruptVector2
);
1017 DPRINT1("InterruptMode2: %x\n", PortConfig
->InterruptMode2
);
1018 DPRINT1("DmaChannel2: %d\n", PortConfig
->DmaChannel2
);
1019 DPRINT1("DmaPort2: %d\n", PortConfig
->DmaPort2
);
1020 DPRINT1("DmaWidth2: %d\n", PortConfig
->DmaWidth2
);
1021 DPRINT1("DmaSpeed2: %d\n", PortConfig
->DmaSpeed2
);
1022 DPRINT1("DeviceExtensionSize: %d\n", PortConfig
->DeviceExtensionSize
);
1023 DPRINT1("SpecificLuExtensionSize: %d\n", PortConfig
->SpecificLuExtensionSize
);
1024 DPRINT1("SrbExtensionSize: %d\n", PortConfig
->SrbExtensionSize
);
1028 if (DeviceExtension
->VirtualAddress
== NULL
&& DeviceExtension
->SrbExtensionSize
)
1030 ScsiPortGetUncachedExtension(&DeviceExtension
->MiniPortDeviceExtension
,
1035 /* Register an interrupt handler for this device */
1036 MappedIrq
= HalGetInterruptVector(PortConfig
->AdapterInterfaceType
,
1037 PortConfig
->SystemIoBusNumber
,
1038 PortConfig
->BusInterruptLevel
,
1042 * Something is wrong in our interrupt conecting code.
1043 * The promise Ultra100TX driver returns 0 for BusInterruptVector
1044 * and a nonzero value for BusInterruptLevel. The driver does only
1045 * work with this fix.
1047 PortConfig
->BusInterruptLevel
,
1049 PortConfig
->BusInterruptVector
,
1053 DPRINT("AdapterInterfaceType %x, SystemIoBusNumber %x, BusInterruptLevel %x, BusInterruptVector %x\n",
1054 PortConfig
->AdapterInterfaceType
, PortConfig
->SystemIoBusNumber
,
1055 PortConfig
->BusInterruptLevel
, PortConfig
->BusInterruptVector
);
1056 Status
= IoConnectInterrupt(&DeviceExtension
->Interrupt
,
1063 PortConfig
->InterruptMode
,
1067 if (!NT_SUCCESS(Status
))
1069 DbgPrint("Could not connect interrupt %d\n",
1070 PortConfig
->BusInterruptVector
);
1074 if (!(HwInitializationData
->HwInitialize
)(&DeviceExtension
->MiniPortDeviceExtension
))
1076 DbgPrint("HwInitialize() failed!");
1077 Status
= STATUS_UNSUCCESSFUL
;
1081 /* Initialize port capabilities */
1082 DeviceExtension
->PortCapabilities
= ExAllocatePool(NonPagedPool
,
1083 sizeof(IO_SCSI_CAPABILITIES
));
1084 if (DeviceExtension
->PortCapabilities
== NULL
)
1086 DbgPrint("Failed to allocate port capabilities!\n");
1087 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1091 PortCapabilities
= DeviceExtension
->PortCapabilities
;
1092 PortCapabilities
->Length
= sizeof(IO_SCSI_CAPABILITIES
);
1093 if (PortConfig
->ScatterGather
== FALSE
||
1094 PortConfig
->NumberOfPhysicalBreaks
>= (0x100000000LL
>> PAGE_SHIFT
) ||
1095 PortConfig
->MaximumTransferLength
< PortConfig
->NumberOfPhysicalBreaks
* PAGE_SIZE
)
1097 PortCapabilities
->MaximumTransferLength
=
1098 PortConfig
->MaximumTransferLength
;
1102 PortCapabilities
->MaximumTransferLength
=
1103 PortConfig
->NumberOfPhysicalBreaks
* PAGE_SIZE
;
1106 PortCapabilities
->MaximumPhysicalPages
=
1107 PortCapabilities
->MaximumTransferLength
/ PAGE_SIZE
;
1108 PortCapabilities
->SupportedAsynchronousEvents
= 0; /* FIXME */
1109 PortCapabilities
->AlignmentMask
=
1110 PortConfig
->AlignmentMask
;
1111 PortCapabilities
->TaggedQueuing
=
1112 PortConfig
->TaggedQueuing
;
1113 PortCapabilities
->AdapterScansDown
=
1114 PortConfig
->AdapterScansDown
;
1115 PortCapabilities
->AdapterUsesPio
= TRUE
; /* FIXME */
1117 /* Scan the adapter for devices */
1118 SpiScanAdapter (DeviceExtension
);
1120 /* Build the registry device map */
1121 SpiBuildDeviceMap (DeviceExtension
,
1122 (PUNICODE_STRING
)Argument2
);
1124 /* Create the dos device link */
1125 swprintf(DosNameBuffer
,
1127 SystemConfig
->ScsiPortCount
);
1128 RtlInitUnicodeString(&DosDeviceName
,
1130 IoCreateSymbolicLink(&DosDeviceName
,
1133 /* Update the system configuration info */
1134 if (PortConfig
->AtdiskPrimaryClaimed
== TRUE
)
1135 SystemConfig
->AtDiskPrimaryAddressClaimed
= TRUE
;
1136 if (PortConfig
->AtdiskSecondaryClaimed
== TRUE
)
1137 SystemConfig
->AtDiskSecondaryAddressClaimed
= TRUE
;
1139 SystemConfig
->ScsiPortCount
++;
1140 PortDeviceObject
= NULL
;
1145 DPRINT("HwFindAdapter() Result: %lu\n", Result
);
1147 ExFreePool (PortConfig
);
1148 IoDeleteDevice (PortDeviceObject
);
1149 PortDeviceObject
= NULL
;
1152 DPRINT("Bus: %lu MaxBus: %lu\n", BusNumber
, MaxBus
);
1153 if (BusNumber
>= MaxBus
)
1155 DPRINT("Scanned all buses!\n");
1156 Status
= STATUS_SUCCESS
;
1163 SlotNumber
.u
.AsULONG
= 0;
1168 /* Clean up the mess */
1169 if (PortDeviceObject
!= NULL
)
1171 DPRINT("Delete device: %p\n", PortDeviceObject
);
1173 DeviceExtension
= PortDeviceObject
->DeviceExtension
;
1175 if (DeviceExtension
->PortCapabilities
!= NULL
)
1177 IoDisconnectInterrupt (DeviceExtension
->Interrupt
);
1178 ExFreePool (DeviceExtension
->PortCapabilities
);
1181 if (DeviceExtension
->PortConfig
!= NULL
)
1183 ExFreePool (DeviceExtension
->PortConfig
);
1186 IoDeleteDevice (PortDeviceObject
);
1189 DPRINT("ScsiPortInitialize() done!\n");
1191 return (DeviceFound
== FALSE
) ? Status
: STATUS_SUCCESS
;
1199 ScsiPortIoMapTransfer(IN PVOID HwDeviceExtension
,
1200 IN PSCSI_REQUEST_BLOCK Srb
,
1201 IN ULONG LogicalAddress
,
1204 DPRINT1("ScsiPortIoMapTransfer()\n");
1213 ScsiPortLogError(IN PVOID HwDeviceExtension
,
1214 IN PSCSI_REQUEST_BLOCK Srb OPTIONAL
,
1221 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
1223 DPRINT1("ScsiPortLogError() called\n");
1224 DPRINT1("Srb %x, PathId %d, TargetId %d, Lun %d, ErrorCode %x, UniqueId %x\n",
1225 Srb
, PathId
, TargetId
, Lun
, ErrorCode
, UniqueId
);
1227 DeviceExtension
= CONTAINING_RECORD(HwDeviceExtension
,
1228 SCSI_PORT_DEVICE_EXTENSION
,
1229 MiniPortDeviceExtension
);
1232 DPRINT("ScsiPortLogError() done\n");
1240 ScsiPortMoveMemory(OUT PVOID Destination
,
1244 RtlMoveMemory(Destination
,
1254 ScsiPortNotification(IN SCSI_NOTIFICATION_TYPE NotificationType
,
1255 IN PVOID HwDeviceExtension
,
1258 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
1261 DPRINT("ScsiPortNotification() called\n");
1263 DeviceExtension
= CONTAINING_RECORD(HwDeviceExtension
,
1264 SCSI_PORT_DEVICE_EXTENSION
,
1265 MiniPortDeviceExtension
);
1267 DPRINT("DeviceExtension %p\n", DeviceExtension
);
1269 va_start(ap
, HwDeviceExtension
);
1271 switch (NotificationType
)
1273 case RequestComplete
:
1275 PSCSI_REQUEST_BLOCK Srb
;
1277 Srb
= (PSCSI_REQUEST_BLOCK
) va_arg (ap
, PSCSI_REQUEST_BLOCK
);
1279 DPRINT("Notify: RequestComplete (Srb %p)\n", Srb
);
1280 DeviceExtension
->Flags
|= IRP_FLAG_COMPLETE
;
1281 Srb
->SrbFlags
&= ~SRB_FLAGS_IS_ACTIVE
;
1286 DPRINT("Notify: NextRequest\n");
1287 DeviceExtension
->Flags
|= IRP_FLAG_NEXT
;
1295 PSCSI_PORT_LUN_EXTENSION LunExtension
;
1297 PathId
= (UCHAR
) va_arg (ap
, int);
1298 TargetId
= (UCHAR
) va_arg (ap
, int);
1299 Lun
= (UCHAR
) va_arg (ap
, int);
1301 DPRINT ("Notify: NextLuRequest(PathId %u TargetId %u Lun %u)\n",
1302 PathId
, TargetId
, Lun
);
1304 LunExtension
= SpiGetLunExtension(DeviceExtension
,
1310 DeviceExtension
->Flags
|= IRP_FLAG_NEXT_LU
;
1311 LunExtension
->Flags
|= IRP_FLAG_NEXT_LU
;
1317 DPRINT1("Notify: ResetDetected\n");
1322 DPRINT1 ("Unsupported notification %lu\n", NotificationType
);
1325 if (KeGetCurrentIrql() >= DISPATCH_LEVEL
)
1327 IoRequestDpc(DeviceExtension
->DeviceObject
,
1333 SpiProcessRequests(DeviceExtension
, NULL
);
1344 ScsiPortSetBusDataByOffset(IN PVOID DeviceExtension
,
1345 IN ULONG BusDataType
,
1346 IN ULONG SystemIoBusNumber
,
1347 IN ULONG SlotNumber
,
1352 DPRINT("ScsiPortSetBusDataByOffset()\n");
1353 return(HalSetBusDataByOffset(BusDataType
,
1366 ScsiPortValidateRange(IN PVOID HwDeviceExtension
,
1367 IN INTERFACE_TYPE BusType
,
1368 IN ULONG SystemIoBusNumber
,
1369 IN SCSI_PHYSICAL_ADDRESS IoAddress
,
1370 IN ULONG NumberOfBytes
,
1371 IN BOOLEAN InIoSpace
)
1373 DPRINT("ScsiPortValidateRange()\n");
1378 /* INTERNAL FUNCTIONS ********************************************************/
1382 SpiGetPciConfigData (IN
struct _HW_INITIALIZATION_DATA
*HwInitializationData
,
1383 IN OUT PPORT_CONFIGURATION_INFORMATION PortConfig
,
1385 IN OUT PPCI_SLOT_NUMBER NextSlotNumber
)
1387 PCI_COMMON_CONFIG PciConfig
;
1388 PCI_SLOT_NUMBER SlotNumber
;
1391 ULONG FunctionNumber
;
1392 CHAR VendorIdString
[8];
1393 CHAR DeviceIdString
[8];
1397 DPRINT ("SpiGetPciConfiguration() called\n");
1399 if (NextSlotNumber
->u
.bits
.FunctionNumber
>= PCI_MAX_FUNCTION
)
1401 NextSlotNumber
->u
.bits
.FunctionNumber
= 0;
1402 NextSlotNumber
->u
.bits
.DeviceNumber
++;
1405 if (NextSlotNumber
->u
.bits
.DeviceNumber
>= PCI_MAX_DEVICES
)
1407 NextSlotNumber
->u
.bits
.DeviceNumber
= 0;
1411 for (DeviceNumber
= NextSlotNumber
->u
.bits
.DeviceNumber
; DeviceNumber
< PCI_MAX_DEVICES
; DeviceNumber
++)
1413 SlotNumber
.u
.bits
.DeviceNumber
= DeviceNumber
;
1415 for (FunctionNumber
= NextSlotNumber
->u
.bits
.FunctionNumber
; FunctionNumber
< PCI_MAX_FUNCTION
; FunctionNumber
++)
1417 SlotNumber
.u
.bits
.FunctionNumber
= FunctionNumber
;
1419 DataSize
= HalGetBusData (PCIConfiguration
,
1421 SlotNumber
.u
.AsULONG
,
1423 PCI_COMMON_HDR_LENGTH
);
1424 if (DataSize
!= PCI_COMMON_HDR_LENGTH
)
1426 if (FunctionNumber
== 0)
1436 sprintf (VendorIdString
, "%04hx", PciConfig
.VendorID
);
1437 sprintf (DeviceIdString
, "%04hx", PciConfig
.DeviceID
);
1439 if (!_strnicmp(VendorIdString
, HwInitializationData
->VendorId
, HwInitializationData
->VendorIdLength
) &&
1440 !_strnicmp(DeviceIdString
, HwInitializationData
->DeviceId
, HwInitializationData
->DeviceIdLength
))
1442 DPRINT ("Found device 0x%04hx 0x%04hx at %1lu %2lu %1lu\n",
1446 SlotNumber
.u
.bits
.DeviceNumber
,
1447 SlotNumber
.u
.bits
.FunctionNumber
);
1449 PortConfig
->BusInterruptLevel
=
1450 PortConfig
->BusInterruptVector
= PciConfig
.u
.type0
.InterruptLine
;
1451 PortConfig
->SlotNumber
= SlotNumber
.u
.AsULONG
;
1453 /* Initialize access ranges */
1454 if (PortConfig
->NumberOfAccessRanges
> 0)
1456 if (PortConfig
->NumberOfAccessRanges
> PCI_TYPE0_ADDRESSES
)
1457 PortConfig
->NumberOfAccessRanges
= PCI_TYPE0_ADDRESSES
;
1459 for (i
= 0; i
< PortConfig
->NumberOfAccessRanges
; i
++)
1461 PortConfig
->AccessRanges
[i
].RangeStart
.QuadPart
=
1462 PciConfig
.u
.type0
.BaseAddresses
[i
] & PCI_ADDRESS_IO_ADDRESS_MASK
;
1463 if (PortConfig
->AccessRanges
[i
].RangeStart
.QuadPart
!= 0)
1465 RangeLength
= (ULONG
)-1;
1466 HalSetBusDataByOffset (PCIConfiguration
,
1468 SlotNumber
.u
.AsULONG
,
1469 (PVOID
)&RangeLength
,
1470 0x10 + (i
* sizeof(ULONG
)),
1473 HalGetBusDataByOffset (PCIConfiguration
,
1475 SlotNumber
.u
.AsULONG
,
1476 (PVOID
)&RangeLength
,
1477 0x10 + (i
* sizeof(ULONG
)),
1480 HalSetBusDataByOffset (PCIConfiguration
,
1482 SlotNumber
.u
.AsULONG
,
1483 (PVOID
)&PciConfig
.u
.type0
.BaseAddresses
[i
],
1484 0x10 + (i
* sizeof(ULONG
)),
1486 if (RangeLength
!= 0)
1488 PortConfig
->AccessRanges
[i
].RangeLength
=
1489 -(RangeLength
& PCI_ADDRESS_IO_ADDRESS_MASK
);
1490 PortConfig
->AccessRanges
[i
].RangeInMemory
=
1491 !(PciConfig
.u
.type0
.BaseAddresses
[i
] & PCI_ADDRESS_IO_SPACE
);
1493 DPRINT("RangeStart 0x%lX RangeLength 0x%lX RangeInMemory %s\n",
1494 PciConfig
.u
.type0
.BaseAddresses
[i
] & PCI_ADDRESS_IO_ADDRESS_MASK
,
1495 -(RangeLength
& PCI_ADDRESS_IO_ADDRESS_MASK
),
1496 (PciConfig
.u
.type0
.BaseAddresses
[i
] & PCI_ADDRESS_IO_SPACE
)?"FALSE":"TRUE");
1502 NextSlotNumber
->u
.bits
.DeviceNumber
= DeviceNumber
;
1503 NextSlotNumber
->u
.bits
.FunctionNumber
= FunctionNumber
;
1505 PortConfig
->SlotNumber
= NextSlotNumber
->u
.AsULONG
;
1507 NextSlotNumber
->u
.bits
.FunctionNumber
+= 1;
1513 if (FunctionNumber
== 0 && !(PciConfig
.HeaderType
& PCI_MULTIFUNCTION
))
1518 NextSlotNumber
->u
.bits
.FunctionNumber
= 0;
1521 DPRINT ("No device found\n");
1528 /**********************************************************************
1530 * ScsiPortCreateClose
1533 * Answer requests for Create/Close calls: a null operation.
1540 * Pointer to a device object.
1543 * Pointer to an IRP.
1549 static NTSTATUS STDCALL
1550 ScsiPortCreateClose(IN PDEVICE_OBJECT DeviceObject
,
1553 DPRINT("ScsiPortCreateClose()\n");
1555 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1556 Irp
->IoStatus
.Information
= FILE_OPENED
;
1558 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1560 return(STATUS_SUCCESS
);
1564 /**********************************************************************
1566 * ScsiPortDispatchScsi
1569 * Answer requests for SCSI calls
1575 * Standard dispatch arguments
1581 static NTSTATUS STDCALL
1582 ScsiPortDispatchScsi(IN PDEVICE_OBJECT DeviceObject
,
1585 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
1586 PSCSI_PORT_LUN_EXTENSION LunExtension
;
1587 PIO_STACK_LOCATION Stack
;
1588 PSCSI_REQUEST_BLOCK Srb
;
1589 NTSTATUS Status
= STATUS_SUCCESS
;
1592 DPRINT("ScsiPortDispatchScsi(DeviceObject %p Irp %p)\n",
1595 DeviceExtension
= DeviceObject
->DeviceExtension
;
1596 Stack
= IoGetCurrentIrpStackLocation(Irp
);
1598 Srb
= Stack
->Parameters
.Scsi
.Srb
;
1601 Status
= STATUS_UNSUCCESSFUL
;
1603 Irp
->IoStatus
.Status
= Status
;
1604 Irp
->IoStatus
.Information
= 0;
1606 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1611 DPRINT("Srb: %p\n", Srb
);
1612 DPRINT("Srb->Function: %lu\n", Srb
->Function
);
1613 DPRINT("PathId: %lu TargetId: %lu Lun: %lu\n", Srb
->PathId
, Srb
->TargetId
, Srb
->Lun
);
1615 LunExtension
= SpiGetLunExtension(DeviceExtension
,
1619 if (LunExtension
== NULL
)
1621 Status
= STATUS_NO_SUCH_DEVICE
;
1623 Srb
->SrbStatus
= SRB_STATUS_NO_DEVICE
;
1624 Irp
->IoStatus
.Status
= Status
;
1625 Irp
->IoStatus
.Information
= 0;
1627 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1632 switch (Srb
->Function
)
1634 case SRB_FUNCTION_EXECUTE_SCSI
:
1635 case SRB_FUNCTION_IO_CONTROL
:
1636 IoMarkIrpPending(Irp
);
1637 Srb
->OriginalRequest
= LunExtension
;
1638 Irp
->Tail
.Overlay
.DriverContext
[3] = Srb
;
1639 SpiProcessRequests(DeviceExtension
, Irp
);
1640 return(STATUS_PENDING
);
1642 case SRB_FUNCTION_SHUTDOWN
:
1643 case SRB_FUNCTION_FLUSH
:
1644 if (DeviceExtension
->PortConfig
->CachesData
== TRUE
)
1646 IoMarkIrpPending(Irp
);
1647 Srb
->OriginalRequest
= LunExtension
;
1648 Irp
->Tail
.Overlay
.DriverContext
[3] = Srb
;
1649 SpiProcessRequests(DeviceExtension
, Irp
);
1650 return(STATUS_PENDING
);
1654 case SRB_FUNCTION_CLAIM_DEVICE
:
1655 DPRINT (" SRB_FUNCTION_CLAIM_DEVICE\n");
1657 /* Reference device object and keep the device object */
1658 ObReferenceObject(DeviceObject
);
1659 LunExtension
->DeviceObject
= DeviceObject
;
1660 LunExtension
->DeviceClaimed
= TRUE
;
1661 Srb
->DataBuffer
= DeviceObject
;
1664 case SRB_FUNCTION_RELEASE_DEVICE
:
1665 DPRINT (" SRB_FUNCTION_RELEASE_DEVICE\n");
1666 DPRINT ("PathId: %lu TargetId: %lu Lun: %lu\n",
1667 Srb
->PathId
, Srb
->TargetId
, Srb
->Lun
);
1669 /* Dereference device object and clear the device object */
1670 ObDereferenceObject(LunExtension
->DeviceObject
);
1671 LunExtension
->DeviceObject
= NULL
;
1672 LunExtension
->DeviceClaimed
= FALSE
;
1676 DPRINT1("SRB function not implemented (Function %lu)\n", Srb
->Function
);
1677 Status
= STATUS_NOT_IMPLEMENTED
;
1681 Irp
->IoStatus
.Status
= Status
;
1682 Irp
->IoStatus
.Information
= DataSize
;
1684 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1690 /**********************************************************************
1692 * ScsiPortDeviceControl
1695 * Answer requests for device control calls
1701 * Standard dispatch arguments
1707 static NTSTATUS STDCALL
1708 ScsiPortDeviceControl(IN PDEVICE_OBJECT DeviceObject
,
1711 PIO_STACK_LOCATION Stack
;
1712 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
1714 DPRINT("ScsiPortDeviceControl()\n");
1716 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1717 Irp
->IoStatus
.Information
= 0;
1720 Stack
= IoGetCurrentIrpStackLocation(Irp
);
1721 DeviceExtension
= DeviceObject
->DeviceExtension
;
1723 switch (Stack
->Parameters
.DeviceIoControl
.IoControlCode
)
1725 case IOCTL_SCSI_GET_DUMP_POINTERS
:
1727 PDUMP_POINTERS DumpPointers
;
1728 DPRINT(" IOCTL_SCSI_GET_DUMP_POINTERS\n");
1729 DumpPointers
= (PDUMP_POINTERS
)Irp
->AssociatedIrp
.SystemBuffer
;
1730 DumpPointers
->DeviceObject
= DeviceObject
;
1732 Irp
->IoStatus
.Information
= sizeof(DUMP_POINTERS
);
1736 case IOCTL_SCSI_GET_CAPABILITIES
:
1738 DPRINT(" IOCTL_SCSI_GET_CAPABILITIES\n");
1740 *((PIO_SCSI_CAPABILITIES
*)Irp
->AssociatedIrp
.SystemBuffer
) =
1741 DeviceExtension
->PortCapabilities
;
1743 Irp
->IoStatus
.Information
= sizeof(PIO_SCSI_CAPABILITIES
);
1747 case IOCTL_SCSI_GET_INQUIRY_DATA
:
1749 DPRINT(" IOCTL_SCSI_GET_INQUIRY_DATA\n");
1751 /* Copy inquiry data to the port device extension */
1752 Irp
->IoStatus
.Information
=
1753 SpiGetInquiryData(DeviceExtension
,
1754 Irp
->AssociatedIrp
.SystemBuffer
);
1755 DPRINT("Inquiry data size: %lu\n", Irp
->IoStatus
.Information
);
1760 DPRINT1(" unknown ioctl code: 0x%lX\n",
1761 Stack
->Parameters
.DeviceIoControl
.IoControlCode
);
1765 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1767 return(STATUS_SUCCESS
);
1771 SpiAllocateSrbExtension(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
1772 PSCSI_REQUEST_BLOCK Srb
)
1776 DPRINT("SpiAllocateSrbExtension\n");
1778 DPRINT("DeviceExtension->VirtualAddress %x, DeviceExtension->SrbExtensionSize %x\n",
1779 DeviceExtension
->VirtualAddress
, DeviceExtension
->SrbExtensionSize
);
1781 Srb
->SrbExtension
= NULL
;
1782 if (DeviceExtension
->VirtualAddress
!= NULL
&&
1783 DeviceExtension
->SrbExtensionSize
> 0)
1785 index
= RtlFindClearBitsAndSet(&DeviceExtension
->SrbExtensionAllocMap
, 1, 0);
1786 if (index
!= 0xffffffff)
1788 DeviceExtension
->CurrentSrbExtensions
++;
1789 Srb
->SrbExtension
= DeviceExtension
->VirtualAddress
+ index
* DeviceExtension
->SrbExtensionSize
;
1792 DPRINT("%x\n", Srb
->SrbExtension
);
1796 SpiFreeSrbExtension(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
1797 PSCSI_REQUEST_BLOCK Srb
)
1801 if (DeviceExtension
->VirtualAddress
!= NULL
&&
1802 DeviceExtension
->SrbExtensionSize
> 0 &&
1803 Srb
->SrbExtension
!= NULL
)
1805 index
= ((ULONG_PTR
)Srb
->SrbExtension
- (ULONG_PTR
)DeviceExtension
->VirtualAddress
) / DeviceExtension
->SrbExtensionSize
;
1806 RtlClearBits(&DeviceExtension
->SrbExtensionAllocMap
, index
, 1);
1807 DeviceExtension
->CurrentSrbExtensions
--;
1809 Srb
->SrbExtension
= NULL
;
1813 static BOOLEAN STDCALL
1814 ScsiPortStartPacket(IN OUT PVOID Context
)
1816 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
1817 PSCSI_REQUEST_BLOCK Srb
;
1819 PIO_STACK_LOCATION IrpStack
;
1821 DPRINT("ScsiPortStartPacket(Context %x) called\n", Context
);
1823 Srb
= (PSCSI_REQUEST_BLOCK
)Context
;
1824 Irp
= (PIRP
)Srb
->OriginalRequest
;
1825 IrpStack
= IoGetCurrentIrpStackLocation(Irp
);
1826 DeviceExtension
= IrpStack
->DeviceObject
->DeviceExtension
;
1828 return(DeviceExtension
->HwStartIo(&DeviceExtension
->MiniPortDeviceExtension
,
1833 static PSCSI_PORT_LUN_EXTENSION
1834 SpiAllocateLunExtension (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
1839 PSCSI_PORT_LUN_EXTENSION LunExtension
;
1840 ULONG LunExtensionSize
;
1842 DPRINT("SpiAllocateLunExtension (%p %u %u %u)\n",
1843 DeviceExtension
, PathId
, TargetId
, Lun
);
1846 sizeof(SCSI_PORT_LUN_EXTENSION
) + DeviceExtension
->LunExtensionSize
;
1847 DPRINT("LunExtensionSize %lu\n", LunExtensionSize
);
1849 LunExtension
= ExAllocatePool(NonPagedPool
,
1851 if (LunExtension
== NULL
)
1856 RtlZeroMemory(LunExtension
,
1859 InsertTailList(&DeviceExtension
->LunExtensionListHead
,
1860 &LunExtension
->List
);
1862 LunExtension
->PathId
= PathId
;
1863 LunExtension
->TargetId
= TargetId
;
1864 LunExtension
->Lun
= Lun
;
1866 LunExtension
->PendingIrpCount
= 0;
1867 LunExtension
->ActiveIrpCount
= 0;
1869 LunExtension
->NextIrp
= NULL
;
1871 return LunExtension
;
1876 SpiRemoveLunExtension (IN PSCSI_PORT_LUN_EXTENSION LunExtension
)
1878 DPRINT("SpiRemoveLunExtension(%p) called\n",
1881 if (LunExtension
== NULL
)
1884 RemoveEntryList (&LunExtension
->List
);
1887 /* Release LUN extersion data */
1890 ExFreePool (LunExtension
);
1896 static PSCSI_PORT_LUN_EXTENSION
1897 SpiGetLunExtension (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
1902 PSCSI_PORT_LUN_EXTENSION LunExtension
;
1905 DPRINT("SpiGetLunExtension(%p %u %u %u) called\n",
1906 DeviceExtension
, PathId
, TargetId
, Lun
);
1908 if (IsListEmpty(&DeviceExtension
->LunExtensionListHead
))
1911 Entry
= DeviceExtension
->LunExtensionListHead
.Flink
;
1912 while (Entry
!= &DeviceExtension
->LunExtensionListHead
)
1914 LunExtension
= CONTAINING_RECORD(Entry
,
1915 SCSI_PORT_LUN_EXTENSION
,
1917 if (LunExtension
->PathId
== PathId
&&
1918 LunExtension
->TargetId
== TargetId
&&
1919 LunExtension
->Lun
== Lun
)
1921 return LunExtension
;
1924 Entry
= Entry
->Flink
;
1932 SpiSendInquiry (IN PDEVICE_OBJECT DeviceObject
,
1933 IN OUT PSCSI_REQUEST_BLOCK Srb
,
1934 IN OUT PIO_STATUS_BLOCK IoStatusBlock
,
1935 IN OUT PKEVENT Event
)
1937 PIO_STACK_LOCATION IrpStack
;
1941 DPRINT ("SpiSendInquiry() called\n");
1944 KeInitializeEvent (Event
,
1948 Irp
= IoBuildDeviceIoControlRequest (IOCTL_SCSI_EXECUTE_OUT
,
1953 Srb
->DataTransferLength
,
1959 DPRINT("IoBuildDeviceIoControlRequest() failed\n");
1960 return STATUS_INSUFFICIENT_RESOURCES
;
1963 /* Attach Srb to the Irp */
1964 IrpStack
= IoGetNextIrpStackLocation (Irp
);
1965 IrpStack
->Parameters
.Scsi
.Srb
= Srb
;
1966 Srb
->OriginalRequest
= Irp
;
1968 /* Call the driver */
1969 Status
= IoCallDriver (DeviceObject
,
1976 SpiScanAdapter (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
)
1978 PSCSI_REQUEST_BLOCK Srb
;
1982 PSCSI_PORT_SCAN_ADAPTER ScanDataArray
;
1983 PSCSI_PORT_SCAN_ADAPTER ScanData
;
1989 PKWAIT_BLOCK WaitBlockArray
;
1991 DPRINT ("SpiScanAdapter() called\n");
1993 MaxCount
= DeviceExtension
->PortConfig
->NumberOfBuses
*
1994 DeviceExtension
->PortConfig
->MaximumNumberOfTargets
;
1996 ScanDataArray
= ExAllocatePool(NonPagedPool
, MaxCount
* (sizeof(SCSI_PORT_SCAN_ADAPTER
) + sizeof(PVOID
) + sizeof(KWAIT_BLOCK
)));
1997 if (ScanDataArray
== NULL
)
2001 EventArray
= (PVOID
*)((PUCHAR
)ScanDataArray
+ MaxCount
* sizeof(SCSI_PORT_SCAN_ADAPTER
));
2002 WaitBlockArray
= (PKWAIT_BLOCK
)((PUCHAR
)EventArray
+ MaxCount
* sizeof(PVOID
));
2004 for (Bus
= 0; Bus
< DeviceExtension
->PortConfig
->NumberOfBuses
; Bus
++)
2006 for (Target
= 0; Target
< DeviceExtension
->PortConfig
->MaximumNumberOfTargets
; Target
++)
2008 ScanData
= &ScanDataArray
[Bus
* DeviceExtension
->PortConfig
->MaximumNumberOfTargets
+ Target
];
2009 ScanData
->Bus
= Bus
;
2010 ScanData
->Target
= Target
;
2012 ScanData
->Active
= FALSE
;
2019 for (i
= 0; i
< MaxCount
; i
++)
2021 ScanData
= &ScanDataArray
[i
];
2022 Srb
= &ScanData
->Srb
;
2023 if (ScanData
->Active
)
2025 if (ScanData
->Status
== STATUS_PENDING
&&
2026 0 == KeReadStateEvent(&ScanData
->Event
))
2033 ScanData
->Status
= ScanData
->IoStatusBlock
.Status
;
2035 ScanData
->Active
= FALSE
;
2036 DPRINT ("Target %lu Lun %lu\n", ScanData
->Target
, ScanData
->Lun
);
2037 DPRINT ("Status %lx Srb.SrbStatus %x\n", ScanData
->Status
, Srb
->SrbStatus
);
2038 DPRINT ("DeviceTypeQualifier %x\n", ((PINQUIRYDATA
)Srb
->DataBuffer
)->DeviceTypeQualifier
);
2040 if (NT_SUCCESS(ScanData
->Status
) &&
2041 (Srb
->SrbStatus
== SRB_STATUS_SUCCESS
||
2042 (Srb
->SrbStatus
== SRB_STATUS_DATA_OVERRUN
&&
2045 * The NT 4.0 driver from an inic950 based scsi controller
2046 * returns only 4 byte of inquiry data, but the device name
2047 * is visible on NT 4.0. We must implement an other way
2048 * to get the complete inquiry data.
2050 Srb
->DataTransferLength
>= /*INQUIRYDATABUFFERSIZE*/4)) &&
2051 ((PINQUIRYDATA
)Srb
->DataBuffer
)->DeviceTypeQualifier
== 0)
2053 /* Copy inquiry data */
2054 RtlCopyMemory (&ScanData
->LunExtension
->InquiryData
,
2056 min(sizeof(INQUIRYDATA
), Srb
->DataTransferLength
));
2061 SpiRemoveLunExtension (ScanData
->LunExtension
);
2062 ScanData
->Lun
= SCSI_MAXIMUM_LOGICAL_UNITS
;
2065 if (ScanData
->Lun
>= SCSI_MAXIMUM_LOGICAL_UNITS
)
2069 RtlZeroMemory(Srb
, sizeof(SCSI_REQUEST_BLOCK
));
2070 Srb
->SrbFlags
= SRB_FLAGS_DATA_IN
;
2071 Srb
->DataBuffer
= ScanData
->DataBuffer
;
2072 Srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
2073 Srb
->DataTransferLength
= 255; //256;
2075 Srb
->Lun
= ScanData
->Lun
;
2076 Srb
->PathId
= ScanData
->Bus
;
2077 Srb
->TargetId
= ScanData
->Target
;
2078 Srb
->SrbStatus
= SRB_STATUS_SUCCESS
;
2079 Srb
->TimeOutValue
= 2;
2080 Cdb
= (PCDB
) &Srb
->Cdb
;
2082 Cdb
->CDB6INQUIRY
.OperationCode
= SCSIOP_INQUIRY
;
2083 Cdb
->CDB6INQUIRY
.AllocationLength
= 255;
2084 Cdb
->CDB6INQUIRY
.LogicalUnitNumber
= ScanData
->Lun
;
2086 RtlZeroMemory(Srb
->DataBuffer
, 256);
2088 ScanData
->LunExtension
= SpiAllocateLunExtension (DeviceExtension
,
2092 if (ScanData
->LunExtension
== NULL
)
2094 DPRINT1("Failed to allocate the LUN extension!\n");
2095 ScanData
->Lun
= SCSI_MAXIMUM_LOGICAL_UNITS
;
2098 ScanData
->Status
= SpiSendInquiry (DeviceExtension
->DeviceObject
,
2100 &ScanData
->IoStatusBlock
,
2102 ScanData
->Active
= TRUE
;
2104 if (ScanData
->Status
== STATUS_PENDING
)
2106 EventArray
[WaitCount
] = &ScanData
->Event
;
2110 if (WaitCount
> 0 && WaitCount
== ActiveCount
)
2112 KeWaitForMultipleObjects(WaitCount
,
2122 while (ActiveCount
> 0);
2124 ExFreePool(ScanDataArray
);
2126 DPRINT ("SpiScanAdapter() done\n");
2131 SpiGetInquiryData(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
2132 OUT PSCSI_ADAPTER_BUS_INFO AdapterBusInfo
)
2134 PSCSI_PORT_LUN_EXTENSION LunExtension
;
2135 PSCSI_INQUIRY_DATA UnitInfo
, PrevUnit
;
2141 DPRINT("SpiGetInquiryData() called\n");
2143 /* Copy inquiry data to the port device extension */
2144 AdapterBusInfo
->NumberOfBuses
= DeviceExtension
->PortConfig
->NumberOfBuses
;
2146 UnitInfo
= (PSCSI_INQUIRY_DATA
)
2147 ((PUCHAR
)AdapterBusInfo
+ sizeof(SCSI_ADAPTER_BUS_INFO
) +
2148 (sizeof(SCSI_BUS_DATA
) * (AdapterBusInfo
->NumberOfBuses
- 1)));
2150 for (Bus
= 0; Bus
< AdapterBusInfo
->NumberOfBuses
; Bus
++)
2152 AdapterBusInfo
->BusData
[Bus
].InitiatorBusId
=
2153 DeviceExtension
->PortConfig
->InitiatorBusId
[Bus
];
2154 AdapterBusInfo
->BusData
[Bus
].InquiryDataOffset
=
2155 (ULONG
)((PUCHAR
)UnitInfo
- (PUCHAR
)AdapterBusInfo
);
2160 for (Target
= 0; Target
< DeviceExtension
->PortConfig
->MaximumNumberOfTargets
; Target
++)
2162 for (Lun
= 0; Lun
< SCSI_MAXIMUM_LOGICAL_UNITS
; Lun
++)
2164 LunExtension
= SpiGetLunExtension(DeviceExtension
,
2168 if (LunExtension
!= NULL
)
2170 DPRINT("(Bus %lu Target %lu Lun %lu)\n",
2173 UnitInfo
->PathId
= Bus
;
2174 UnitInfo
->TargetId
= Target
;
2175 UnitInfo
->Lun
= Lun
;
2176 UnitInfo
->InquiryDataLength
= INQUIRYDATABUFFERSIZE
;
2177 RtlCopyMemory (&UnitInfo
->InquiryData
,
2178 &LunExtension
->InquiryData
,
2179 INQUIRYDATABUFFERSIZE
);
2180 if (PrevUnit
!= NULL
)
2182 PrevUnit
->NextInquiryDataOffset
=
2183 (ULONG
)((ULONG_PTR
)UnitInfo
-(ULONG_PTR
)AdapterBusInfo
);
2185 PrevUnit
= UnitInfo
;
2186 UnitInfo
= (PSCSI_INQUIRY_DATA
)((PUCHAR
)UnitInfo
+ sizeof(SCSI_INQUIRY_DATA
)+INQUIRYDATABUFFERSIZE
-1);
2191 DPRINT("UnitCount: %lu\n", UnitCount
);
2192 AdapterBusInfo
->BusData
[Bus
].NumberOfLogicalUnits
= UnitCount
;
2195 AdapterBusInfo
->BusData
[Bus
].InquiryDataOffset
= 0;
2199 DPRINT("Data size: %lu\n", (ULONG
)UnitInfo
- (ULONG
)AdapterBusInfo
);
2201 return (ULONG
)((PUCHAR
)UnitInfo
-(PUCHAR
)AdapterBusInfo
);
2205 static BOOLEAN STDCALL
2206 ScsiPortIsr(IN PKINTERRUPT Interrupt
,
2207 IN PVOID ServiceContext
)
2209 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
2211 DPRINT("ScsiPortIsr() called!\n");
2213 DeviceExtension
= (PSCSI_PORT_DEVICE_EXTENSION
)ServiceContext
;
2215 return DeviceExtension
->HwInterrupt(&DeviceExtension
->MiniPortDeviceExtension
);
2226 // IN PDEVICE_OBJECT DpcDeviceObject
2228 // IN PVOID DpcContext
2231 ScsiPortDpc(IN PKDPC Dpc
,
2232 IN PDEVICE_OBJECT DpcDeviceObject
,
2234 IN PVOID DpcContext
)
2236 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
2238 DPRINT("ScsiPortDpc(Dpc %p DpcDeviceObject %p DpcIrp %p DpcContext %p)\n",
2239 Dpc
, DpcDeviceObject
, DpcIrp
, DpcContext
);
2241 DeviceExtension
= (PSCSI_PORT_DEVICE_EXTENSION
)DpcContext
;
2243 SpiProcessRequests(DeviceExtension
, NULL
);
2245 DPRINT("ScsiPortDpc() done\n");
2251 // This function handles timeouts and other time delayed processing
2256 // IN PDEVICE_OBJECT DeviceObject Device object registered with timer
2257 // IN PVOID Context the Controller extension for the
2258 // controller the device is on
2261 ScsiPortIoTimer(PDEVICE_OBJECT DeviceObject
,
2264 DPRINT1("ScsiPortIoTimer()\n");
2268 static PSCSI_REQUEST_BLOCK
2269 ScsiPortInitSenseRequestSrb(PSCSI_REQUEST_BLOCK OriginalSrb
)
2271 PSCSI_REQUEST_BLOCK Srb
;
2275 Length
= sizeof(SCSI_REQUEST_BLOCK
) + sizeof(SENSE_DATA
) + 32;
2276 Srb
= ExAllocatePoolWithTag(NonPagedPool
,
2278 TAG('S', 'S', 'r', 'b'));
2284 RtlZeroMemory(Srb
, Length
);
2286 Srb
->PathId
= OriginalSrb
->PathId
;
2287 Srb
->TargetId
= OriginalSrb
->TargetId
;
2288 Srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
2289 Srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
2290 Srb
->SrbFlags
= SRB_FLAGS_DATA_IN
| SRB_FLAGS_DISABLE_SYNCH_TRANSFER
;
2291 Srb
->OriginalRequest
= OriginalSrb
->OriginalRequest
;
2293 Srb
->TimeOutValue
= 4;
2296 /* The DataBuffer must be located in contiguous physical memory if
2297 * the miniport driver uses dma for the sense info. The size of
2298 * the sense data is 18 byte. If the buffer starts at a 32 byte
2299 * boundary than is the buffer always in one memory page.
2301 Srb
->DataBuffer
= (PVOID
)ROUND_UP((ULONG_PTR
)(Srb
+ 1), 32);
2302 Srb
->DataTransferLength
= sizeof(SENSE_DATA
);
2304 Cdb
= (PCDB
)Srb
->Cdb
;
2305 Cdb
->CDB6INQUIRY
.OperationCode
= SCSIOP_REQUEST_SENSE
;
2306 Cdb
->CDB6INQUIRY
.AllocationLength
= sizeof(SENSE_DATA
);
2311 /**********************************************************************
2316 * Builds the registry device map of all device which are attached
2317 * to the given SCSI HBA port. The device map is located at:
2318 * \Registry\Machine\DeviceMap\Scsi
2328 * Name of registry driver service key.
2335 SpiBuildDeviceMap (PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
2336 PUNICODE_STRING RegistryPath
)
2338 PSCSI_PORT_LUN_EXTENSION LunExtension
;
2339 OBJECT_ATTRIBUTES ObjectAttributes
;
2340 UNICODE_STRING KeyName
;
2341 UNICODE_STRING ValueName
;
2342 WCHAR NameBuffer
[64];
2345 HANDLE ScsiPortKey
= NULL
;
2346 HANDLE ScsiBusKey
= NULL
;
2347 HANDLE ScsiInitiatorKey
= NULL
;
2348 HANDLE ScsiTargetKey
= NULL
;
2349 HANDLE ScsiLunKey
= NULL
;
2352 ULONG CurrentTarget
;
2359 DPRINT("SpiBuildDeviceMap() called\n");
2361 if (DeviceExtension
== NULL
|| RegistryPath
== NULL
)
2363 DPRINT1("Invalid parameter\n");
2364 return(STATUS_INVALID_PARAMETER
);
2367 /* Open or create the 'Scsi' subkey */
2368 RtlRosInitUnicodeStringFromLiteral(&KeyName
,
2369 L
"\\Registry\\Machine\\Hardware\\DeviceMap\\Scsi");
2370 InitializeObjectAttributes(&ObjectAttributes
,
2372 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
,
2375 Status
= ZwCreateKey(&ScsiKey
,
2380 REG_OPTION_VOLATILE
,
2382 if (!NT_SUCCESS(Status
))
2384 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status
);
2388 /* Create new 'Scsi Port X' subkey */
2389 DPRINT("Scsi Port %lu\n",
2390 DeviceExtension
->PortNumber
);
2392 swprintf(NameBuffer
,
2394 DeviceExtension
->PortNumber
);
2395 RtlInitUnicodeString(&KeyName
,
2397 InitializeObjectAttributes(&ObjectAttributes
,
2402 Status
= ZwCreateKey(&ScsiPortKey
,
2407 REG_OPTION_VOLATILE
,
2410 if (!NT_SUCCESS(Status
))
2412 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status
);
2417 * Create port-specific values
2420 /* Set 'DMA Enabled' (REG_DWORD) value */
2421 UlongData
= (ULONG
)!DeviceExtension
->PortCapabilities
->AdapterUsesPio
;
2422 DPRINT(" DMA Enabled = %s\n", (UlongData
) ? "TRUE" : "FALSE");
2423 RtlInitUnicodeString(&ValueName
,
2425 Status
= ZwSetValueKey(ScsiPortKey
,
2431 if (!NT_SUCCESS(Status
))
2433 DPRINT("ZwSetValueKey('DMA Enabled') failed (Status %lx)\n", Status
);
2434 ZwClose(ScsiPortKey
);
2438 /* Set 'Driver' (REG_SZ) value */
2439 DriverName
= wcsrchr(RegistryPath
->Buffer
, L
'\\') + 1;
2440 RtlInitUnicodeString(&ValueName
,
2442 Status
= ZwSetValueKey(ScsiPortKey
,
2447 (wcslen(DriverName
) + 1) * sizeof(WCHAR
));
2448 if (!NT_SUCCESS(Status
))
2450 DPRINT("ZwSetValueKey('Driver') failed (Status %lx)\n", Status
);
2451 ZwClose(ScsiPortKey
);
2455 /* Set 'Interrupt' (REG_DWORD) value (NT4 only) */
2456 UlongData
= (ULONG
)DeviceExtension
->PortConfig
->BusInterruptLevel
;
2457 DPRINT(" Interrupt = %lu\n", UlongData
);
2458 RtlInitUnicodeString(&ValueName
,
2460 Status
= ZwSetValueKey(ScsiPortKey
,
2466 if (!NT_SUCCESS(Status
))
2468 DPRINT("ZwSetValueKey('Interrupt') failed (Status %lx)\n", Status
);
2469 ZwClose(ScsiPortKey
);
2473 /* Set 'IOAddress' (REG_DWORD) value (NT4 only) */
2474 UlongData
= ScsiPortConvertPhysicalAddressToUlong(DeviceExtension
->PortConfig
->AccessRanges
[0].RangeStart
);
2475 DPRINT(" IOAddress = %lx\n", UlongData
);
2476 RtlInitUnicodeString(&ValueName
,
2478 Status
= ZwSetValueKey(ScsiPortKey
,
2484 if (!NT_SUCCESS(Status
))
2486 DPRINT("ZwSetValueKey('IOAddress') failed (Status %lx)\n", Status
);
2487 ZwClose(ScsiPortKey
);
2491 /* Enumerate buses */
2492 for (BusNumber
= 0; BusNumber
< DeviceExtension
->PortConfig
->NumberOfBuses
; BusNumber
++)
2494 /* Create 'Scsi Bus X' key */
2495 DPRINT(" Scsi Bus %lu\n", BusNumber
);
2496 swprintf(NameBuffer
,
2499 RtlInitUnicodeString(&KeyName
,
2501 InitializeObjectAttributes(&ObjectAttributes
,
2506 Status
= ZwCreateKey(&ScsiBusKey
,
2511 REG_OPTION_VOLATILE
,
2513 if (!NT_SUCCESS(Status
))
2515 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status
);
2519 /* Create 'Initiator Id X' key */
2520 DPRINT(" Initiator Id %u\n",
2521 DeviceExtension
->PortConfig
->InitiatorBusId
[BusNumber
]);
2522 swprintf(NameBuffer
,
2524 (unsigned int)(UCHAR
)DeviceExtension
->PortConfig
->InitiatorBusId
[BusNumber
]);
2525 RtlInitUnicodeString(&KeyName
,
2527 InitializeObjectAttributes(&ObjectAttributes
,
2532 Status
= ZwCreateKey(&ScsiInitiatorKey
,
2537 REG_OPTION_VOLATILE
,
2539 if (!NT_SUCCESS(Status
))
2541 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status
);
2545 /* FIXME: Are there any initiator values (??) */
2547 ZwClose(ScsiInitiatorKey
);
2548 ScsiInitiatorKey
= NULL
;
2551 /* Enumerate targets */
2552 CurrentTarget
= (ULONG
)-1;
2553 ScsiTargetKey
= NULL
;
2554 for (Target
= 0; Target
< DeviceExtension
->PortConfig
->MaximumNumberOfTargets
; Target
++)
2556 for (Lun
= 0; Lun
< SCSI_MAXIMUM_LOGICAL_UNITS
; Lun
++)
2558 LunExtension
= SpiGetLunExtension(DeviceExtension
,
2562 if (LunExtension
!= NULL
)
2564 if (Target
!= CurrentTarget
)
2566 /* Close old target key */
2567 if (ScsiTargetKey
!= NULL
)
2569 ZwClose(ScsiTargetKey
);
2570 ScsiTargetKey
= NULL
;
2573 /* Create 'Target Id X' key */
2574 DPRINT(" Target Id %lu\n", Target
);
2575 swprintf(NameBuffer
,
2578 RtlInitUnicodeString(&KeyName
,
2580 InitializeObjectAttributes(&ObjectAttributes
,
2585 Status
= ZwCreateKey(&ScsiTargetKey
,
2590 REG_OPTION_VOLATILE
,
2592 if (!NT_SUCCESS(Status
))
2594 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status
);
2598 CurrentTarget
= Target
;
2601 /* Create 'Logical Unit Id X' key */
2602 DPRINT(" Logical Unit Id %lu\n", Lun
);
2603 swprintf(NameBuffer
,
2604 L
"Logical Unit Id %lu",
2606 RtlInitUnicodeString(&KeyName
,
2608 InitializeObjectAttributes(&ObjectAttributes
,
2613 Status
= ZwCreateKey(&ScsiLunKey
,
2618 REG_OPTION_VOLATILE
,
2620 if (!NT_SUCCESS(Status
))
2622 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status
);
2626 /* Set 'Identifier' (REG_SZ) value */
2627 swprintf(NameBuffer
,
2629 LunExtension
->InquiryData
.VendorId
,
2630 LunExtension
->InquiryData
.ProductId
,
2631 LunExtension
->InquiryData
.ProductRevisionLevel
);
2632 DPRINT(" Identifier = '%S'\n", NameBuffer
);
2633 RtlInitUnicodeString(&ValueName
,
2635 Status
= ZwSetValueKey(ScsiLunKey
,
2640 (wcslen(NameBuffer
) + 1) * sizeof(WCHAR
));
2641 if (!NT_SUCCESS(Status
))
2643 DPRINT("ZwSetValueKey('Identifier') failed (Status %lx)\n", Status
);
2647 /* Set 'Type' (REG_SZ) value */
2648 switch (LunExtension
->InquiryData
.DeviceType
)
2651 TypeName
= L
"DiskPeripheral";
2654 TypeName
= L
"TapePeripheral";
2657 TypeName
= L
"PrinterPeripheral";
2660 TypeName
= L
"WormPeripheral";
2663 TypeName
= L
"CdRomPeripheral";
2666 TypeName
= L
"ScannerPeripheral";
2669 TypeName
= L
"OpticalDiskPeripheral";
2672 TypeName
= L
"MediumChangerPeripheral";
2675 TypeName
= L
"CommunicationPeripheral";
2678 TypeName
= L
"OtherPeripheral";
2681 DPRINT(" Type = '%S'\n", TypeName
);
2682 RtlInitUnicodeString(&ValueName
,
2684 Status
= ZwSetValueKey(ScsiLunKey
,
2689 (wcslen(TypeName
) + 1) * sizeof(WCHAR
));
2690 if (!NT_SUCCESS(Status
))
2692 DPRINT("ZwSetValueKey('Type') failed (Status %lx)\n", Status
);
2696 ZwClose(ScsiLunKey
);
2701 /* Close old target key */
2702 if (ScsiTargetKey
!= NULL
)
2704 ZwClose(ScsiTargetKey
);
2705 ScsiTargetKey
= NULL
;
2709 ZwClose(ScsiBusKey
);
2714 if (ScsiLunKey
!= NULL
)
2715 ZwClose (ScsiLunKey
);
2717 if (ScsiInitiatorKey
!= NULL
)
2718 ZwClose (ScsiInitiatorKey
);
2720 if (ScsiTargetKey
!= NULL
)
2721 ZwClose (ScsiTargetKey
);
2723 if (ScsiBusKey
!= NULL
)
2724 ZwClose (ScsiBusKey
);
2726 if (ScsiPortKey
!= NULL
)
2727 ZwClose (ScsiPortKey
);
2729 DPRINT("SpiBuildDeviceMap() done\n");
2735 SpiRemoveActiveIrp(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
2739 PSCSI_PORT_LUN_EXTENSION LunExtension
;
2741 LunExtension
= Irp
->Tail
.Overlay
.DriverContext
[2];
2742 InterlockedDecrement((PLONG
)&LunExtension
->ActiveIrpCount
);
2743 InterlockedDecrement((PLONG
)&DeviceExtension
->ActiveIrpCount
);
2746 InterlockedExchangePointer(&PrevIrp
->Tail
.Overlay
.DriverContext
[0],
2747 Irp
->Tail
.Overlay
.DriverContext
[0]);
2751 InterlockedExchangePointer(&DeviceExtension
->NextIrp
,
2752 Irp
->Tail
.Overlay
.DriverContext
[0]);
2754 if (LunExtension
->NextIrp
== Irp
)
2756 InterlockedExchangePointer(&LunExtension
->NextIrp
,
2757 Irp
->Tail
.Overlay
.DriverContext
[1]);
2762 CurrentIrp
= LunExtension
->NextIrp
;
2765 if (CurrentIrp
->Tail
.Overlay
.DriverContext
[1] == Irp
)
2767 InterlockedExchangePointer(&CurrentIrp
->Tail
.Overlay
.DriverContext
[1],
2768 Irp
->Tail
.Overlay
.DriverContext
[1]);
2771 CurrentIrp
= CurrentIrp
->Tail
.Overlay
.DriverContext
[1];
2778 SpiAddActiveIrp(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
2781 PSCSI_PORT_LUN_EXTENSION LunExtension
;
2782 PSCSI_REQUEST_BLOCK Srb
;
2783 LunExtension
= Irp
->Tail
.Overlay
.DriverContext
[2];
2784 Srb
= Irp
->Tail
.Overlay
.DriverContext
[3];
2785 Irp
->Tail
.Overlay
.DriverContext
[0] = (PVOID
)DeviceExtension
->NextIrp
;
2786 InterlockedExchangePointer(&DeviceExtension
->NextIrp
, Irp
);
2787 Irp
->Tail
.Overlay
.DriverContext
[1] = (PVOID
)LunExtension
->NextIrp
;
2788 InterlockedExchangePointer(&LunExtension
->NextIrp
, Irp
);
2792 SpiProcessRequests(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
2796 * Using of some fields from Srb and Irp while processing requests:
2799 * Srb->OriginalRequest -> LunExtension
2800 * Irp->Tail.Overlay.DriverContext[3] -> original Srb
2801 * IoStack->Parameters.Scsi.Srb -> original Srb
2803 * Irp is within the pending irp list:
2804 * Srb->OriginalRequest -> LunExtension
2805 * Irp->Tail.Overlay.DriverContext[0] and DriverContext[1] -> ListEntry for queue
2806 * Irp->Tail.Overlay.DriverContext[2] -> sort key (from Srb->QueueSortKey)
2807 * Irp->Tail.Overlay.DriverContext[3] -> current Srb (original or sense request)
2808 * IoStack->Parameters.Scsi.Srb -> original Srb
2810 * Irp is within the active irp list or while other processing:
2811 * Srb->OriginalRequest -> Irp
2812 * Irp->Tail.Overlay.DriverContext[0] -> next irp, DeviceExtension->NextIrp is head.
2813 * Irp->Tail.Overlay.DriverContext[1] -> next irp, LunExtension->NextIrp is head.
2814 * Irp->Tail.Overlay.DriverContext[2] -> LunExtension
2815 * Irp->Tail.Overlay.DriverContext[3] -> current Srb (original or sense request)
2816 * IoStack->Parameters.Scsi.Srb -> original Srb
2818 PIO_STACK_LOCATION IrpStack
;
2819 PSCSI_PORT_LUN_EXTENSION LunExtension
;
2820 PLIST_ENTRY ListEntry
;
2823 LIST_ENTRY NextIrpListHead
;
2824 LIST_ENTRY CompleteIrpListHead
;
2825 PSCSI_REQUEST_BLOCK Srb
;
2826 PSCSI_REQUEST_BLOCK OriginalSrb
;
2829 DPRINT("SpiProcessRequests() called\n");
2831 InitializeListHead(&NextIrpListHead
);
2832 InitializeListHead(&CompleteIrpListHead
);
2834 KeAcquireSpinLock(&DeviceExtension
->Lock
, &oldIrql
);
2838 Srb
= NextIrp
->Tail
.Overlay
.DriverContext
[3];
2841 * Is this the right place to set this flag ?
2843 NextIrp
->Tail
.Overlay
.DriverContext
[2] = (PVOID
)Srb
->QueueSortKey
;
2844 LunExtension
= Srb
->OriginalRequest
;
2846 ListEntry
= DeviceExtension
->PendingIrpListHead
.Flink
;
2847 while (ListEntry
!= &DeviceExtension
->PendingIrpListHead
)
2849 Irp
= CONTAINING_RECORD(ListEntry
, IRP
, Tail
.Overlay
.DriverContext
[0]);
2850 if ((ULONG
)Irp
->Tail
.Overlay
.DriverContext
[2] > Srb
->QueueSortKey
)
2854 ListEntry
= ListEntry
->Flink
;
2856 InsertTailList(ListEntry
, (PLIST_ENTRY
)&NextIrp
->Tail
.Overlay
.DriverContext
[0]);
2857 DeviceExtension
->PendingIrpCount
++;
2858 LunExtension
->PendingIrpCount
++;
2861 while (DeviceExtension
->Flags
& IRP_FLAG_COMPLETE
||
2862 (((DeviceExtension
->SrbExtensionSize
== 0 || DeviceExtension
->CurrentSrbExtensions
< DeviceExtension
->MaxSrbExtensions
) &&
2863 DeviceExtension
->PendingIrpCount
> 0 &&
2864 (DeviceExtension
->Flags
& (IRP_FLAG_NEXT
|IRP_FLAG_NEXT_LU
) || DeviceExtension
->NextIrp
== NULL
))))
2866 DPRINT ("RequestComplete %d, NextRequest %d, NextLuRequest %d, PendingIrpCount %d, ActiveIrpCount %d\n",
2867 DeviceExtension
->Flags
& IRP_FLAG_COMPLETE
? 1 : 0,
2868 DeviceExtension
->Flags
& IRP_FLAG_NEXT
? 1 : 0,
2869 DeviceExtension
->Flags
& IRP_FLAG_NEXT_LU
? 1 : 0,
2870 DeviceExtension
->PendingIrpCount
,
2871 DeviceExtension
->ActiveIrpCount
);
2874 if (DeviceExtension
->Flags
& IRP_FLAG_COMPLETE
)
2876 DeviceExtension
->Flags
&= ~IRP_FLAG_COMPLETE
;
2878 Irp
= DeviceExtension
->NextIrp
;
2881 NextIrp
= (PIRP
)Irp
->Tail
.Overlay
.DriverContext
[0];
2882 Srb
= Irp
->Tail
.Overlay
.DriverContext
[3];
2883 if (!(Srb
->SrbFlags
& SRB_FLAGS_IS_ACTIVE
))
2885 BOOLEAN CompleteThisRequest
;
2886 LunExtension
= Irp
->Tail
.Overlay
.DriverContext
[2];
2887 IrpStack
= IoGetCurrentIrpStackLocation(Irp
);
2888 OriginalSrb
= IrpStack
->Parameters
.Scsi
.Srb
;
2890 if (Srb
->SrbStatus
== SRB_STATUS_BUSY
)
2892 SpiRemoveActiveIrp(DeviceExtension
, Irp
, PrevIrp
);
2893 SpiFreeSrbExtension(DeviceExtension
, OriginalSrb
);
2894 InsertHeadList(&DeviceExtension
->PendingIrpListHead
, (PLIST_ENTRY
)&Irp
->Tail
.Overlay
.DriverContext
[0]);
2895 DeviceExtension
->PendingIrpCount
++;
2896 LunExtension
->PendingIrpCount
++;
2901 if (OriginalSrb
!= Srb
)
2903 SENSE_DATA
* SenseInfoBuffer
;
2905 SenseInfoBuffer
= Srb
->DataBuffer
;
2907 DPRINT("Got sense data!\n");
2909 DPRINT("Valid: %x\n", SenseInfoBuffer
->Valid
);
2910 DPRINT("ErrorCode: %x\n", SenseInfoBuffer
->ErrorCode
);
2911 DPRINT("SenseKey: %x\n", SenseInfoBuffer
->SenseKey
);
2912 DPRINT("SenseCode: %x\n", SenseInfoBuffer
->AdditionalSenseCode
);
2914 /* Copy sense data */
2915 RtlCopyMemory(OriginalSrb
->SenseInfoBuffer
,
2917 sizeof(SENSE_DATA
));
2918 OriginalSrb
->SrbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2920 CompleteThisRequest
= TRUE
;
2922 else if (SRB_STATUS(Srb
->SrbStatus
) != SRB_STATUS_SUCCESS
&&
2923 Srb
->ScsiStatus
== SCSISTAT_CHECK_CONDITION
&&
2924 Srb
->SenseInfoBuffer
!= NULL
&&
2925 Srb
->SenseInfoBufferLength
>= sizeof(SENSE_DATA
) &&
2926 !(Srb
->SrbStatus
& SRB_STATUS_AUTOSENSE_VALID
))
2928 DPRINT("SCSIOP_REQUEST_SENSE required!\n");
2930 Srb
= ScsiPortInitSenseRequestSrb(OriginalSrb
);
2934 CompleteThisRequest
= FALSE
;
2935 Irp
->Tail
.Overlay
.DriverContext
[3] = Srb
;
2936 SpiRemoveActiveIrp(DeviceExtension
, Irp
, PrevIrp
);
2937 SpiFreeSrbExtension(DeviceExtension
, Srb
);
2939 Srb
->OriginalRequest
= LunExtension
;
2940 Irp
->Tail
.Overlay
.DriverContext
[2] = 0;
2942 InsertHeadList(&DeviceExtension
->PendingIrpListHead
, (PLIST_ENTRY
)&Irp
->Tail
.Overlay
.DriverContext
[0]);
2943 DeviceExtension
->PendingIrpCount
++;
2944 LunExtension
->PendingIrpCount
++;
2950 CompleteThisRequest
= TRUE
;
2955 DPRINT("Complete Request\n");
2956 CompleteThisRequest
= TRUE
;
2958 if (CompleteThisRequest
)
2960 SpiRemoveActiveIrp(DeviceExtension
, Irp
, PrevIrp
);
2961 InsertHeadList(&CompleteIrpListHead
, (PLIST_ENTRY
)&Irp
->Tail
.Overlay
.DriverContext
[0]);
2962 SpiFreeSrbExtension(DeviceExtension
, OriginalSrb
);
2975 if (!IsListEmpty(&CompleteIrpListHead
))
2977 KeReleaseSpinLockFromDpcLevel(&DeviceExtension
->Lock
);
2978 while (!IsListEmpty(&CompleteIrpListHead
))
2980 ListEntry
= RemoveTailList(&CompleteIrpListHead
);
2981 Irp
= CONTAINING_RECORD(ListEntry
, IRP
, Tail
.Overlay
.DriverContext
[0]);
2982 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2984 KeAcquireSpinLockAtDpcLevel(&DeviceExtension
->Lock
);
2986 if (DeviceExtension
->Flags
& (IRP_FLAG_NEXT
|IRP_FLAG_NEXT_LU
) &&
2987 (DeviceExtension
->SrbExtensionSize
== 0 || DeviceExtension
->CurrentSrbExtensions
< DeviceExtension
->MaxSrbExtensions
))
2989 BOOLEAN StartThisRequest
;
2990 ListEntry
= DeviceExtension
->PendingIrpListHead
.Flink
;
2991 while (ListEntry
!= &DeviceExtension
->PendingIrpListHead
)
2993 Irp
= CONTAINING_RECORD(ListEntry
, IRP
, Tail
.Overlay
.DriverContext
[0]);
2994 ListEntry
= ListEntry
->Flink
;
2995 Srb
= Irp
->Tail
.Overlay
.DriverContext
[3];
2996 LunExtension
= Srb
->OriginalRequest
;
2997 if (DeviceExtension
->SrbExtensionSize
> 0 &&
2998 DeviceExtension
->CurrentSrbExtensions
>= DeviceExtension
->MaxSrbExtensions
)
3002 if (LunExtension
->Flags
& IRP_FLAG_NEXT_LU
)
3004 StartThisRequest
= TRUE
;
3005 LunExtension
->Flags
&= ~IRP_FLAG_NEXT_LU
;
3006 DeviceExtension
->Flags
&= ~IRP_FLAG_NEXT_LU
;
3008 else if (DeviceExtension
->Flags
& IRP_FLAG_NEXT
&&
3009 LunExtension
->ActiveIrpCount
== 0)
3011 StartThisRequest
= TRUE
;
3012 DeviceExtension
->Flags
&= ~IRP_FLAG_NEXT
;
3016 StartThisRequest
= FALSE
;
3018 if (StartThisRequest
)
3020 LunExtension
->PendingIrpCount
--;
3021 DeviceExtension
->PendingIrpCount
--;
3022 Srb
->SrbFlags
|= SRB_FLAGS_IS_ACTIVE
;
3023 LunExtension
->ActiveIrpCount
++;
3024 DeviceExtension
->ActiveIrpCount
++;
3026 RemoveEntryList((PLIST_ENTRY
)&Irp
->Tail
.Overlay
.DriverContext
[0]);
3027 Irp
->Tail
.Overlay
.DriverContext
[2] = LunExtension
;
3028 Srb
->OriginalRequest
= Irp
;
3029 SpiAllocateSrbExtension(DeviceExtension
, Srb
);
3031 InsertHeadList(&NextIrpListHead
, (PLIST_ENTRY
)&Irp
->Tail
.Overlay
.DriverContext
[0]);
3036 if (!IsListEmpty(&NextIrpListHead
))
3038 while (!IsListEmpty(&NextIrpListHead
))
3040 ListEntry
= RemoveTailList(&NextIrpListHead
);
3041 Irp
= CONTAINING_RECORD(ListEntry
, IRP
, Tail
.Overlay
.DriverContext
[0]);
3042 KeReleaseSpinLockFromDpcLevel(&DeviceExtension
->Lock
);
3045 SpiStartIo(DeviceExtension
, Irp
);
3046 KeAcquireSpinLockAtDpcLevel(&DeviceExtension
->Lock
);
3050 if (!IsListEmpty(&DeviceExtension
->PendingIrpListHead
) &&
3051 DeviceExtension
->NextIrp
== NULL
&&
3052 (DeviceExtension
->SrbExtensionSize
== 0 || DeviceExtension
->CurrentSrbExtensions
< DeviceExtension
->MaxSrbExtensions
))
3054 ListEntry
= RemoveHeadList(&DeviceExtension
->PendingIrpListHead
);
3055 Irp
= CONTAINING_RECORD(ListEntry
, IRP
, Tail
.Overlay
.DriverContext
[0]);
3056 Srb
= Irp
->Tail
.Overlay
.DriverContext
[3];
3057 LunExtension
= Srb
->OriginalRequest
;
3058 Irp
->Tail
.Overlay
.DriverContext
[2] = LunExtension
;
3059 Srb
->OriginalRequest
= Irp
;
3061 LunExtension
->PendingIrpCount
--;
3062 DeviceExtension
->PendingIrpCount
--;
3063 Srb
->SrbFlags
|= SRB_FLAGS_IS_ACTIVE
;
3064 LunExtension
->ActiveIrpCount
++;
3065 DeviceExtension
->ActiveIrpCount
++;
3067 SpiAllocateSrbExtension(DeviceExtension
, Srb
);
3068 KeReleaseSpinLockFromDpcLevel(&DeviceExtension
->Lock
);
3070 /* Start this irp */
3071 SpiStartIo(DeviceExtension
, Irp
);
3072 KeAcquireSpinLockAtDpcLevel(&DeviceExtension
->Lock
);
3075 KeReleaseSpinLock(&DeviceExtension
->Lock
, oldIrql
);
3077 DPRINT("SpiProcessRequests() done\n");
3081 SpiStartIo(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
3084 PSCSI_PORT_LUN_EXTENSION LunExtension
;
3085 PSCSI_REQUEST_BLOCK Srb
;
3087 DPRINT("SpiStartIo() called!\n");
3089 assert(KeGetCurrentIrql() == DISPATCH_LEVEL
);
3091 Srb
= Irp
->Tail
.Overlay
.DriverContext
[3];
3092 LunExtension
= Irp
->Tail
.Overlay
.DriverContext
[2];
3094 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
3095 Irp
->IoStatus
.Information
= Srb
->DataTransferLength
;
3097 SpiAddActiveIrp(DeviceExtension
, Irp
);
3099 if (!KeSynchronizeExecution(DeviceExtension
->Interrupt
,
3100 ScsiPortStartPacket
,
3103 DPRINT1("Synchronization failed!\n");
3104 DPRINT1("Irp %x, Srb->Function %02x, Srb->Cdb[0] %02x, Srb->SrbStatus %02x\n", Irp
, Srb
->Function
, Srb
->Cdb
[0], Srb
->SrbStatus
);
3105 ScsiPortNotification(RequestComplete
,
3106 &DeviceExtension
->MiniPortDeviceExtension
,
3110 DPRINT("SpiStartIo() done\n");