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.
19 /* $Id: scsiport.c,v 1.59 2004/06/07 20:03:00 hbirr Exp $
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 <rosrtl/string.h>
40 #include "scsiport_int.h"
42 /* TYPES *********************************************************************/
44 #define IRP_FLAG_COMPLETE 0x00000001
45 #define IRP_FLAG_NEXT 0x00000002
46 #define IRP_FLAG_NEXT_LU 0x00000004
48 #define MAX_SRB_EXTENSIONS 32
50 /* GLOBALS *******************************************************************/
53 SpiProcessRequests(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
57 SpiStartIo(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
61 SpiGetPciConfigData (IN
struct _HW_INITIALIZATION_DATA
*HwInitializationData
,
62 IN OUT PPORT_CONFIGURATION_INFORMATION PortConfig
,
64 IN OUT PPCI_SLOT_NUMBER NextSlotNumber
);
66 static NTSTATUS STDCALL
67 ScsiPortCreateClose(IN PDEVICE_OBJECT DeviceObject
,
70 static NTSTATUS STDCALL
71 ScsiPortDispatchScsi(IN PDEVICE_OBJECT DeviceObject
,
74 static NTSTATUS STDCALL
75 ScsiPortDeviceControl(IN PDEVICE_OBJECT DeviceObject
,
78 static BOOLEAN STDCALL
79 ScsiPortStartPacket(IN OUT PVOID Context
);
82 static PSCSI_PORT_LUN_EXTENSION
83 SpiAllocateLunExtension (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
89 SpiRemoveLunExtension (IN PSCSI_PORT_LUN_EXTENSION LunExtension
);
91 static PSCSI_PORT_LUN_EXTENSION
92 SpiGetLunExtension (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
98 SpiSendInquiry (IN PDEVICE_OBJECT DeviceObject
,
99 IN OUT PSCSI_REQUEST_BLOCK Srb
,
100 IN OUT PIO_STATUS_BLOCK IoStatusBlock
,
101 IN OUT PKEVENT Event
);
104 SpiScanAdapter (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
);
107 SpiGetInquiryData (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
108 OUT PSCSI_ADAPTER_BUS_INFO AdapterBusInfo
);
110 static BOOLEAN STDCALL
111 ScsiPortIsr(IN PKINTERRUPT Interrupt
,
112 IN PVOID ServiceContext
);
115 ScsiPortDpc(IN PKDPC Dpc
,
116 IN PDEVICE_OBJECT DpcDeviceObject
,
118 IN PVOID DpcContext
);
121 ScsiPortIoTimer(PDEVICE_OBJECT DeviceObject
,
124 static PSCSI_REQUEST_BLOCK
125 ScsiPortInitSenseRequestSrb(PSCSI_REQUEST_BLOCK OriginalSrb
);
128 SpiBuildDeviceMap (PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
129 PUNICODE_STRING RegistryPath
);
132 SpiAllocateSrbExtension(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
133 PSCSI_REQUEST_BLOCK Srb
);
136 SpiFreeSrbExtension(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
137 PSCSI_REQUEST_BLOCK Srb
);
140 /* FUNCTIONS *****************************************************************/
142 /**********************************************************************
147 * This function initializes the driver.
154 * System allocated Driver Object for this driver.
157 * Name of registry driver service key.
164 DriverEntry(IN PDRIVER_OBJECT DriverObject
,
165 IN PUNICODE_STRING RegistryPath
)
167 DPRINT("ScsiPort Driver %s\n", VERSION
);
168 return(STATUS_SUCCESS
);
172 /**********************************************************************
177 * Prints debugging messages.
184 * Debug level of the given message.
187 * Pointer to printf()-compatible format string.
190 Additional output data (see printf()).
199 ScsiDebugPrint(IN ULONG DebugPrintLevel
,
200 IN PCHAR DebugMessage
,
207 if (DebugPrintLevel
> InternalDebugLevel
)
211 va_start(ap
, DebugMessage
);
212 vsprintf(Buffer
, DebugMessage
, ap
);
223 ScsiPortCompleteRequest(IN PVOID HwDeviceExtension
,
229 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
230 PSCSI_PORT_LUN_EXTENSION LunExtension
;
233 PSCSI_REQUEST_BLOCK Srb
;
235 DPRINT("ScsiPortCompleteRequest(HwDeviceExtension %x, PathId %d, TargetId %d, Lun %d, SrbStatus %x)\n",
236 HwDeviceExtension
, PathId
, TargetId
, Lun
, SrbStatus
);
238 DeviceExtension
= CONTAINING_RECORD(HwDeviceExtension
,
239 SCSI_PORT_DEVICE_EXTENSION
,
240 MiniPortDeviceExtension
);
242 Entry
= DeviceExtension
->LunExtensionListHead
.Flink
;
243 while (Entry
!= &DeviceExtension
->LunExtensionListHead
)
245 LunExtension
= CONTAINING_RECORD(Entry
,
246 SCSI_PORT_LUN_EXTENSION
,
251 if (PathId
== (UCHAR
)SP_UNTAGGED
||
252 (PathId
== LunExtension
->PathId
&& TargetId
== (UCHAR
)SP_UNTAGGED
) ||
253 (PathId
== LunExtension
->PathId
&& TargetId
== LunExtension
->TargetId
&& Lun
== (UCHAR
)SP_UNTAGGED
) ||
254 (PathId
== LunExtension
->PathId
&& TargetId
== LunExtension
->TargetId
&& Lun
== LunExtension
->Lun
))
256 Irp
= LunExtension
->NextIrp
;
259 Srb
= (PSCSI_REQUEST_BLOCK
)Irp
->Tail
.Overlay
.DriverContext
[3];
260 if (Srb
->SrbStatus
& SRB_FLAGS_IS_ACTIVE
)
262 Srb
->SrbStatus
= SrbStatus
;
263 ScsiPortNotification(RequestComplete
,
267 Irp
= Irp
->Tail
.Overlay
.DriverContext
[1];
270 Entry
= Entry
->Flink
;
279 ScsiPortConvertPhysicalAddressToUlong(IN SCSI_PHYSICAL_ADDRESS Address
)
281 DPRINT("ScsiPortConvertPhysicalAddressToUlong()\n");
282 return(Address
.u
.LowPart
);
290 ScsiPortFlushDma(IN PVOID HwDeviceExtension
)
292 DPRINT("ScsiPortFlushDma()\n");
301 ScsiPortFreeDeviceBase(IN PVOID HwDeviceExtension
,
302 IN PVOID MappedAddress
)
304 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
305 PSCSI_PORT_DEVICE_BASE DeviceBase
;
308 DPRINT("ScsiPortFreeDeviceBase() called\n");
310 DeviceExtension
= CONTAINING_RECORD(HwDeviceExtension
,
311 SCSI_PORT_DEVICE_EXTENSION
,
312 MiniPortDeviceExtension
);
313 if (IsListEmpty(&DeviceExtension
->DeviceBaseListHead
))
316 Entry
= DeviceExtension
->DeviceBaseListHead
.Flink
;
317 while (Entry
!= &DeviceExtension
->DeviceBaseListHead
)
319 DeviceBase
= CONTAINING_RECORD(Entry
,
320 SCSI_PORT_DEVICE_BASE
,
322 if (DeviceBase
->MappedAddress
== MappedAddress
)
324 MmUnmapIoSpace(DeviceBase
->MappedAddress
,
325 DeviceBase
->NumberOfBytes
);
326 RemoveEntryList(Entry
);
327 ExFreePool(DeviceBase
);
332 Entry
= Entry
->Flink
;
341 ScsiPortGetBusData(IN PVOID DeviceExtension
,
342 IN ULONG BusDataType
,
343 IN ULONG SystemIoBusNumber
,
348 return(HalGetBusData(BusDataType
,
360 ScsiPortGetDeviceBase(IN PVOID HwDeviceExtension
,
361 IN INTERFACE_TYPE BusType
,
362 IN ULONG SystemIoBusNumber
,
363 IN SCSI_PHYSICAL_ADDRESS IoAddress
,
364 IN ULONG NumberOfBytes
,
365 IN BOOLEAN InIoSpace
)
367 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
368 PHYSICAL_ADDRESS TranslatedAddress
;
369 PSCSI_PORT_DEVICE_BASE DeviceBase
;
373 DPRINT ("ScsiPortGetDeviceBase() called\n");
375 AddressSpace
= (ULONG
)InIoSpace
;
376 if (HalTranslateBusAddress(BusType
,
380 &TranslatedAddress
) == FALSE
)
384 if (AddressSpace
!= 0)
385 return((PVOID
)TranslatedAddress
.u
.LowPart
);
387 MappedAddress
= MmMapIoSpace(TranslatedAddress
,
391 DeviceBase
= ExAllocatePool(NonPagedPool
,
392 sizeof(SCSI_PORT_DEVICE_BASE
));
393 if (DeviceBase
== NULL
)
394 return(MappedAddress
);
396 DeviceBase
->MappedAddress
= MappedAddress
;
397 DeviceBase
->NumberOfBytes
= NumberOfBytes
;
398 DeviceBase
->IoAddress
= IoAddress
;
399 DeviceBase
->SystemIoBusNumber
= SystemIoBusNumber
;
401 DeviceExtension
= CONTAINING_RECORD(HwDeviceExtension
,
402 SCSI_PORT_DEVICE_EXTENSION
,
403 MiniPortDeviceExtension
);
405 InsertHeadList(&DeviceExtension
->DeviceBaseListHead
,
408 return(MappedAddress
);
416 ScsiPortGetLogicalUnit(IN PVOID HwDeviceExtension
,
421 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
422 PSCSI_PORT_LUN_EXTENSION LunExtension
;
425 DPRINT("ScsiPortGetLogicalUnit() called\n");
427 DeviceExtension
= CONTAINING_RECORD(HwDeviceExtension
,
428 SCSI_PORT_DEVICE_EXTENSION
,
429 MiniPortDeviceExtension
);
430 if (IsListEmpty(&DeviceExtension
->LunExtensionListHead
))
433 Entry
= DeviceExtension
->LunExtensionListHead
.Flink
;
434 while (Entry
!= &DeviceExtension
->LunExtensionListHead
)
436 LunExtension
= CONTAINING_RECORD(Entry
,
437 SCSI_PORT_LUN_EXTENSION
,
439 if (LunExtension
->PathId
== PathId
&&
440 LunExtension
->TargetId
== TargetId
&&
441 LunExtension
->Lun
== Lun
)
443 return (PVOID
)&LunExtension
->MiniportLunExtension
;
446 Entry
= Entry
->Flink
;
456 SCSI_PHYSICAL_ADDRESS STDCALL
457 ScsiPortGetPhysicalAddress(IN PVOID HwDeviceExtension
,
458 IN PSCSI_REQUEST_BLOCK Srb OPTIONAL
,
459 IN PVOID VirtualAddress
,
462 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
463 SCSI_PHYSICAL_ADDRESS PhysicalAddress
;
464 SCSI_PHYSICAL_ADDRESS NextPhysicalAddress
;
465 ULONG BufferLength
= 0;
469 DPRINT("ScsiPortGetPhysicalAddress(%p %p %p %p)\n",
470 HwDeviceExtension
, Srb
, VirtualAddress
, Length
);
472 DeviceExtension
= CONTAINING_RECORD(HwDeviceExtension
,
473 SCSI_PORT_DEVICE_EXTENSION
,
474 MiniPortDeviceExtension
);
482 EndAddress
= DeviceExtension
->VirtualAddress
+ DeviceExtension
->CommonBufferLength
;
483 if (VirtualAddress
>= DeviceExtension
->VirtualAddress
&& VirtualAddress
< EndAddress
)
485 Offset
= (ULONG_PTR
)VirtualAddress
- (ULONG_PTR
)DeviceExtension
->VirtualAddress
;
486 PhysicalAddress
.QuadPart
= DeviceExtension
->PhysicalAddress
.QuadPart
+ Offset
;
487 BufferLength
= (ULONG_PTR
)EndAddress
- (ULONG_PTR
)VirtualAddress
;
492 * The given virtual address is not within the range
493 * of the drivers uncached extension or srb extension.
497 * Check if the address is a sense info buffer of an active srb.
499 PhysicalAddress
= MmGetPhysicalAddress(VirtualAddress
);
500 if (PhysicalAddress
.QuadPart
== 0LL)
503 return PhysicalAddress
;
505 BufferLength
= PAGE_SIZE
- PhysicalAddress
.u
.LowPart
% PAGE_SIZE
;
510 EndAddress
= Srb
->DataBuffer
+ Srb
->DataTransferLength
;
511 if (VirtualAddress
== NULL
)
513 VirtualAddress
= Srb
->DataBuffer
;
515 else if (VirtualAddress
< Srb
->DataBuffer
|| VirtualAddress
>= EndAddress
)
517 EndAddress
= Srb
->SenseInfoBuffer
+ Srb
->SenseInfoBufferLength
;
518 if (VirtualAddress
< Srb
->SenseInfoBuffer
|| VirtualAddress
>= EndAddress
)
520 PhysicalAddress
.QuadPart
= 0LL;
522 return PhysicalAddress
;
526 PhysicalAddress
= MmGetPhysicalAddress(VirtualAddress
);
527 if (PhysicalAddress
.QuadPart
== 0LL)
530 return PhysicalAddress
;
533 BufferLength
= PAGE_SIZE
- (ULONG_PTR
)VirtualAddress
% PAGE_SIZE
;
534 while (VirtualAddress
+ BufferLength
< EndAddress
)
536 NextPhysicalAddress
= MmGetPhysicalAddress(VirtualAddress
+ BufferLength
);
537 if (PhysicalAddress
.QuadPart
+ BufferLength
!= NextPhysicalAddress
.QuadPart
)
541 BufferLength
+= PAGE_SIZE
;
543 if (VirtualAddress
+ BufferLength
>= EndAddress
)
545 BufferLength
= EndAddress
- VirtualAddress
;
550 *Length
= BufferLength
;
552 DPRINT("Address %I64x, Length %d\n", PhysicalAddress
.QuadPart
, BufferLength
);
553 return PhysicalAddress
;
560 PSCSI_REQUEST_BLOCK STDCALL
561 ScsiPortGetSrb(IN PVOID HwDeviceExtension
,
567 DPRINT1("ScsiPortGetSrb() unimplemented\n");
577 ScsiPortGetUncachedExtension(IN PVOID HwDeviceExtension
,
578 IN PPORT_CONFIGURATION_INFORMATION ConfigInfo
,
579 IN ULONG NumberOfBytes
)
581 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
582 DEVICE_DESCRIPTION DeviceDescription
;
584 DPRINT("ScsiPortGetUncachedExtension(%p %p %lu)\n",
585 HwDeviceExtension
, ConfigInfo
, NumberOfBytes
);
587 DeviceExtension
= CONTAINING_RECORD(HwDeviceExtension
,
588 SCSI_PORT_DEVICE_EXTENSION
,
589 MiniPortDeviceExtension
);
591 /* Check for allocated common DMA buffer */
592 if (DeviceExtension
->VirtualAddress
!= NULL
)
594 DPRINT1("The HBA has already got a common DMA buffer!\n");
598 /* Check for DMA adapter object */
599 if (DeviceExtension
->AdapterObject
== NULL
)
601 /* Initialize DMA adapter description */
602 RtlZeroMemory(&DeviceDescription
,
603 sizeof(DEVICE_DESCRIPTION
));
604 DeviceDescription
.Version
= DEVICE_DESCRIPTION_VERSION
;
605 DeviceDescription
.Master
= ConfigInfo
->Master
;
606 DeviceDescription
.ScatterGather
= ConfigInfo
->ScatterGather
;
607 DeviceDescription
.DemandMode
= ConfigInfo
->DemandMode
;
608 DeviceDescription
.Dma32BitAddresses
= ConfigInfo
->Dma32BitAddresses
;
609 DeviceDescription
.BusNumber
= ConfigInfo
->SystemIoBusNumber
;
610 DeviceDescription
.DmaChannel
= ConfigInfo
->DmaChannel
;
611 DeviceDescription
.InterfaceType
= ConfigInfo
->AdapterInterfaceType
;
612 DeviceDescription
.DmaWidth
= ConfigInfo
->DmaWidth
;
613 DeviceDescription
.DmaSpeed
= ConfigInfo
->DmaSpeed
;
614 DeviceDescription
.MaximumLength
= ConfigInfo
->MaximumTransferLength
;
615 DeviceDescription
.DmaPort
= ConfigInfo
->DmaPort
;
617 /* Get a DMA adapter object */
618 DeviceExtension
->AdapterObject
= HalGetAdapter(&DeviceDescription
,
619 &DeviceExtension
->MapRegisterCount
);
620 if (DeviceExtension
->AdapterObject
== NULL
)
622 DPRINT1("HalGetAdapter() failed\n");
627 /* Allocate a common DMA buffer */
628 DeviceExtension
->CommonBufferLength
=
629 NumberOfBytes
+ PAGE_ROUND_UP(DeviceExtension
->SrbExtensionSize
* MAX_SRB_EXTENSIONS
);
630 DeviceExtension
->VirtualAddress
=
631 HalAllocateCommonBuffer(DeviceExtension
->AdapterObject
,
632 DeviceExtension
->CommonBufferLength
,
633 &DeviceExtension
->PhysicalAddress
,
635 DeviceExtension
->VirtualAddressMap
= 0;
636 if (DeviceExtension
->VirtualAddress
== NULL
)
638 DPRINT1("HalAllocateCommonBuffer() failed!\n");
639 DeviceExtension
->CommonBufferLength
= 0;
643 return (PVOID
)((ULONG_PTR
)DeviceExtension
->VirtualAddress
+
644 PAGE_ROUND_UP(DeviceExtension
->SrbExtensionSize
* MAX_SRB_EXTENSIONS
));
652 ScsiPortGetVirtualAddress(IN PVOID HwDeviceExtension
,
653 IN SCSI_PHYSICAL_ADDRESS PhysicalAddress
)
655 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
658 DPRINT("ScsiPortGetVirtualAddress(%p %I64x)\n",
659 HwDeviceExtension
, PhysicalAddress
.QuadPart
);
661 DeviceExtension
= CONTAINING_RECORD(HwDeviceExtension
,
662 SCSI_PORT_DEVICE_EXTENSION
,
663 MiniPortDeviceExtension
);
665 if (DeviceExtension
->PhysicalAddress
.QuadPart
> PhysicalAddress
.QuadPart
)
668 Offset
= (ULONG
)(PhysicalAddress
.QuadPart
- DeviceExtension
->PhysicalAddress
.QuadPart
);
669 if (Offset
>= DeviceExtension
->CommonBufferLength
)
672 return (PVOID
)((ULONG_PTR
)DeviceExtension
->VirtualAddress
+ Offset
);
676 /**********************************************************************
681 * Initializes SCSI port driver specific data.
688 * Pointer to the miniport driver's driver object.
691 * Pointer to the miniport driver's registry path.
693 * HwInitializationData
694 * Pointer to port driver specific configuration data.
697 Miniport driver specific context.
706 ScsiPortInitialize(IN PVOID Argument1
,
708 IN
struct _HW_INITIALIZATION_DATA
*HwInitializationData
,
711 PDRIVER_OBJECT DriverObject
= (PDRIVER_OBJECT
)Argument1
;
712 // PUNICODE_STRING RegistryPath = (PUNICODE_STRING)Argument2;
713 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
714 PCONFIGURATION_INFORMATION SystemConfig
;
715 PPORT_CONFIGURATION_INFORMATION PortConfig
;
716 ULONG DeviceExtensionSize
;
717 ULONG PortConfigSize
;
719 BOOLEAN DeviceFound
= FALSE
;
725 PCI_SLOT_NUMBER SlotNumber
;
727 PDEVICE_OBJECT PortDeviceObject
;
728 WCHAR NameBuffer
[80];
729 UNICODE_STRING DeviceName
;
730 WCHAR DosNameBuffer
[80];
731 UNICODE_STRING DosDeviceName
;
732 PIO_SCSI_CAPABILITIES PortCapabilities
;
738 DPRINT ("ScsiPortInitialize() called!\n");
740 DPRINT1("HwInitializationDataSize: %d\n", HwInitializationData
->HwInitializationDataSize
);
741 DPRINT1("AdapterInterfaceType: %d\n", HwInitializationData
->AdapterInterfaceType
);
742 DPRINT1("HwInitialize: %x\n", HwInitializationData
->HwInitialize
);
743 DPRINT1("HwStartIo: %x\n", HwInitializationData
->HwStartIo
);
744 DPRINT1("HwInterrupt: %x\n", HwInitializationData
->HwInterrupt
);
745 DPRINT1("HwFindAdapter: %x\n", HwInitializationData
->HwFindAdapter
);
746 DPRINT1("HwResetBus: %x\n", HwInitializationData
->HwResetBus
);
747 DPRINT1("HwDmaStarted: %x\n", HwInitializationData
->HwDmaStarted
);
748 DPRINT1("HwAdapterState: %x\n", HwInitializationData
->HwAdapterState
);
749 DPRINT1("DeviceExtensionSize: %d\n", HwInitializationData
->DeviceExtensionSize
);
750 DPRINT1("SpecificLuExtensionSize: %d\n", HwInitializationData
->SpecificLuExtensionSize
);
751 DPRINT1("SrbExtensionSize: %d\n", HwInitializationData
->SrbExtensionSize
);
752 DPRINT1("NumberOfAccessRanges: %d\n", HwInitializationData
->NumberOfAccessRanges
);
753 DPRINT1("Reserved: %x\n", HwInitializationData
->Reserved
);
754 DPRINT1("MapBuffers: %d\n", HwInitializationData
->MapBuffers
);
755 DPRINT1("NeedPhysicalAddresses: %d\n", HwInitializationData
->NeedPhysicalAddresses
);
756 DPRINT1("TaggedQueueing: %d\n", HwInitializationData
->TaggedQueueing
);
757 DPRINT1("AutoRequestSense: %d\n", HwInitializationData
->AutoRequestSense
);
758 DPRINT1("MultipleRequestPerLu: %d\n", HwInitializationData
->MultipleRequestPerLu
);
759 DPRINT1("ReceiveEvent: %d\n", HwInitializationData
->ReceiveEvent
);
760 DPRINT1("VendorIdLength: %d\n", HwInitializationData
->VendorIdLength
);
761 DPRINT1("VendorId: %x\n", HwInitializationData
->VendorId
);
762 DPRINT1("ReservedUshort: %d\n", HwInitializationData
->ReservedUshort
);
763 DPRINT1("DeviceIdLength: %d\n", HwInitializationData
->DeviceIdLength
);
764 DPRINT1("DeviceId: %x\n", HwInitializationData
->DeviceId
);
766 if ((HwInitializationData
->HwInitialize
== NULL
) ||
767 (HwInitializationData
->HwStartIo
== NULL
) ||
768 (HwInitializationData
->HwInterrupt
== NULL
) ||
769 (HwInitializationData
->HwFindAdapter
== NULL
) ||
770 (HwInitializationData
->HwResetBus
== NULL
))
771 return(STATUS_INVALID_PARAMETER
);
773 DriverObject
->DriverStartIo
= NULL
;
774 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = ScsiPortCreateClose
;
775 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = ScsiPortCreateClose
;
776 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = ScsiPortDeviceControl
;
777 DriverObject
->MajorFunction
[IRP_MJ_SCSI
] = ScsiPortDispatchScsi
;
779 SystemConfig
= IoGetConfigurationInformation();
781 DeviceExtensionSize
= sizeof(SCSI_PORT_DEVICE_EXTENSION
) +
782 HwInitializationData
->DeviceExtensionSize
;
783 PortConfigSize
= sizeof(PORT_CONFIGURATION_INFORMATION
) +
784 HwInitializationData
->NumberOfAccessRanges
* sizeof(ACCESS_RANGE
);
787 MaxBus
= (HwInitializationData
->AdapterInterfaceType
== PCIBus
) ? 8 : 1;
788 DPRINT("MaxBus: %lu\n", MaxBus
);
790 PortDeviceObject
= NULL
;
792 SlotNumber
.u
.AsULONG
= 0;
795 /* Create a unicode device name */
796 swprintf (NameBuffer
,
797 L
"\\Device\\ScsiPort%lu",
798 SystemConfig
->ScsiPortCount
);
799 RtlInitUnicodeString (&DeviceName
,
802 DPRINT("Creating device: %wZ\n", &DeviceName
);
804 /* Create the port device */
805 Status
= IoCreateDevice (DriverObject
,
808 FILE_DEVICE_CONTROLLER
,
812 if (!NT_SUCCESS(Status
))
814 DbgPrint ("IoCreateDevice call failed! (Status 0x%lX)\n", Status
);
815 PortDeviceObject
= NULL
;
819 DPRINT ("Created device: %wZ (%p)\n", &DeviceName
, PortDeviceObject
);
821 /* Set the buffering strategy here... */
822 PortDeviceObject
->Flags
|= DO_DIRECT_IO
;
823 PortDeviceObject
->AlignmentRequirement
= FILE_WORD_ALIGNMENT
;
825 DeviceExtension
= PortDeviceObject
->DeviceExtension
;
826 RtlZeroMemory(DeviceExtension
, DeviceExtensionSize
);
827 DeviceExtension
->Length
= DeviceExtensionSize
;
828 DeviceExtension
->DeviceObject
= PortDeviceObject
;
829 DeviceExtension
->PortNumber
= SystemConfig
->ScsiPortCount
;
831 DeviceExtension
->MiniPortExtensionSize
= HwInitializationData
->DeviceExtensionSize
;
832 DeviceExtension
->LunExtensionSize
= HwInitializationData
->SpecificLuExtensionSize
;
833 DeviceExtension
->SrbExtensionSize
= HwInitializationData
->SrbExtensionSize
;
834 DeviceExtension
->HwStartIo
= HwInitializationData
->HwStartIo
;
835 DeviceExtension
->HwInterrupt
= HwInitializationData
->HwInterrupt
;
837 DeviceExtension
->AdapterObject
= NULL
;
838 DeviceExtension
->MapRegisterCount
= 0;
839 DeviceExtension
->PhysicalAddress
.QuadPart
= 0ULL;
840 DeviceExtension
->VirtualAddress
= NULL
;
841 DeviceExtension
->CommonBufferLength
= 0;
843 /* Initialize the device base list */
844 InitializeListHead (&DeviceExtension
->DeviceBaseListHead
);
846 /* Initialize the irp lists */
847 InitializeListHead (&DeviceExtension
->PendingIrpListHead
);
848 DeviceExtension
->NextIrp
= NULL
;
849 DeviceExtension
->PendingIrpCount
= 0;
850 DeviceExtension
->ActiveIrpCount
= 0;
852 /* Initialize LUN-Extension list */
853 InitializeListHead (&DeviceExtension
->LunExtensionListHead
);
855 /* Initialize the spin lock in the controller extension */
856 KeInitializeSpinLock (&DeviceExtension
->Lock
);
858 /* Initialize the DPC object */
859 IoInitializeDpcRequest (PortDeviceObject
,
862 /* Initialize the device timer */
863 DeviceExtension
->TimerState
= IDETimerIdle
;
864 DeviceExtension
->TimerCount
= 0;
865 IoInitializeTimer (PortDeviceObject
,
869 /* Allocate and initialize port configuration info */
870 DeviceExtension
->PortConfig
= ExAllocatePool (NonPagedPool
,
872 if (DeviceExtension
->PortConfig
== NULL
)
874 Status
= STATUS_INSUFFICIENT_RESOURCES
;
877 RtlZeroMemory (DeviceExtension
->PortConfig
,
880 PortConfig
= DeviceExtension
->PortConfig
;
881 PortConfig
->Length
= sizeof(PORT_CONFIGURATION_INFORMATION
);
882 PortConfig
->SystemIoBusNumber
= BusNumber
;
883 PortConfig
->AdapterInterfaceType
= HwInitializationData
->AdapterInterfaceType
;
884 PortConfig
->InterruptMode
=
885 (PortConfig
->AdapterInterfaceType
== PCIBus
) ? LevelSensitive
: Latched
;
886 PortConfig
->MaximumTransferLength
= SP_UNINITIALIZED_VALUE
;
887 PortConfig
->NumberOfPhysicalBreaks
= SP_UNINITIALIZED_VALUE
;
888 PortConfig
->DmaChannel
= SP_UNINITIALIZED_VALUE
;
889 PortConfig
->DmaPort
= SP_UNINITIALIZED_VALUE
;
890 PortConfig
->DmaWidth
= 0;
891 PortConfig
->DmaSpeed
= Compatible
;
892 PortConfig
->AlignmentMask
= 0;
893 PortConfig
->NumberOfAccessRanges
= HwInitializationData
->NumberOfAccessRanges
;
894 PortConfig
->NumberOfBuses
= 0;
896 for (i
= 0; i
< SCSI_MAXIMUM_BUSES
; i
++)
897 PortConfig
->InitiatorBusId
[i
] = 255;
899 PortConfig
->ScatterGather
= FALSE
;
900 PortConfig
->Master
= FALSE
;
901 PortConfig
->CachesData
= FALSE
;
902 PortConfig
->AdapterScansDown
= FALSE
;
903 PortConfig
->AtdiskPrimaryClaimed
= SystemConfig
->AtDiskPrimaryAddressClaimed
;
904 PortConfig
->AtdiskSecondaryClaimed
= SystemConfig
->AtDiskSecondaryAddressClaimed
;
905 PortConfig
->Dma32BitAddresses
= FALSE
;
906 PortConfig
->DemandMode
= FALSE
;
907 PortConfig
->MapBuffers
= HwInitializationData
->MapBuffers
;
908 PortConfig
->NeedPhysicalAddresses
= HwInitializationData
->NeedPhysicalAddresses
;
909 PortConfig
->TaggedQueuing
= HwInitializationData
->TaggedQueueing
;
910 PortConfig
->AutoRequestSense
= HwInitializationData
->AutoRequestSense
;
911 PortConfig
->MultipleRequestPerLu
= HwInitializationData
->MultipleRequestPerLu
;
912 PortConfig
->ReceiveEvent
= HwInitializationData
->ReceiveEvent
;
913 PortConfig
->RealModeInitialized
= FALSE
;
914 PortConfig
->BufferAccessScsiPortControlled
= FALSE
;
915 PortConfig
->MaximumNumberOfTargets
= SCSI_MAXIMUM_TARGETS
;
916 // PortConfig->MaximumNumberOfLogicalUnits = SCSI_MAXIMUM_LOGICAL_UNITS;
918 PortConfig
->SrbExtensionSize
= HwInitializationData
->SrbExtensionSize
;
919 PortConfig
->SpecificLuExtensionSize
= HwInitializationData
->SpecificLuExtensionSize
;
921 PortConfig
->AccessRanges
= (PACCESS_RANGE
)(PortConfig
+ 1);
923 /* Search for matching PCI device */
924 if ((HwInitializationData
->AdapterInterfaceType
== PCIBus
) &&
925 (HwInitializationData
->VendorIdLength
> 0) &&
926 (HwInitializationData
->VendorId
!= NULL
) &&
927 (HwInitializationData
->DeviceIdLength
> 0) &&
928 (HwInitializationData
->DeviceId
!= NULL
))
930 /* Get PCI device data */
931 DPRINT("VendorId '%.*s' DeviceId '%.*s'\n",
932 HwInitializationData
->VendorIdLength
,
933 HwInitializationData
->VendorId
,
934 HwInitializationData
->DeviceIdLength
,
935 HwInitializationData
->DeviceId
);
937 if (!SpiGetPciConfigData (HwInitializationData
,
942 Status
= STATUS_UNSUCCESSFUL
;
947 /* Note: HwFindAdapter is called once for each bus */
949 DPRINT("Calling HwFindAdapter() for Bus %lu\n", PortConfig
->SystemIoBusNumber
);
950 Result
= (HwInitializationData
->HwFindAdapter
)(&DeviceExtension
->MiniPortDeviceExtension
,
952 0, /* BusInformation */
953 "", /* ArgumentString */
956 DPRINT("HwFindAdapter() Result: %lu Again: %s\n",
957 Result
, (Again
) ? "True" : "False");
959 if (Result
== SP_RETURN_FOUND
)
961 DPRINT("ScsiPortInitialize(): Found HBA! (%x)\n", PortConfig
->BusInterruptVector
);
964 DPRINT1("SystemIoBusNumber: %x\n", PortConfig
->SystemIoBusNumber
);
965 DPRINT1("AdapterInterfaceType: %x\n", PortConfig
->AdapterInterfaceType
);
966 DPRINT1("BusInterruptLevel: %x\n", PortConfig
->BusInterruptLevel
);
967 DPRINT1("BusInterruptVector: %x\n", PortConfig
->BusInterruptVector
);
968 DPRINT1("InterruptMode: %x\n", PortConfig
->InterruptMode
);
969 DPRINT1("MaximumTransferLength: %x\n", PortConfig
->MaximumTransferLength
);
970 DPRINT1("NumberOfPhysicalBreaks: %x\n", PortConfig
->NumberOfPhysicalBreaks
);
971 DPRINT1("DmaChannel: %x\n", PortConfig
->DmaChannel
);
972 DPRINT1("DmaPort: %d\n", PortConfig
->DmaPort
);
973 DPRINT1("DmaWidth: %d\n", PortConfig
->DmaWidth
);
974 DPRINT1("DmaSpeed: %d\n", PortConfig
->DmaSpeed
);
975 DPRINT1("AlignmentMask: %d\n", PortConfig
->AlignmentMask
);
976 DPRINT1("NumberOfAccessRanges: %d\n", PortConfig
->NumberOfAccessRanges
);
977 DPRINT1("NumberOfBuses: %d\n", PortConfig
->NumberOfBuses
);
978 DPRINT1("ScatterGather: %d\n", PortConfig
->ScatterGather
);
979 DPRINT1("Master: %d\n", PortConfig
->Master
);
980 DPRINT1("CachesData: %d\n", PortConfig
->CachesData
);
981 DPRINT1("AdapterScansDown: %d\n", PortConfig
->AdapterScansDown
);
982 DPRINT1("AtdiskPrimaryClaimed: %d\n", PortConfig
->AtdiskPrimaryClaimed
);
983 DPRINT1("AtdiskSecondaryClaimed: %d\n", PortConfig
->AtdiskSecondaryClaimed
);
984 DPRINT1("Dma32BitAddresses: %d\n", PortConfig
->Dma32BitAddresses
);
985 DPRINT1("DemandMode: %d\n", PortConfig
->DemandMode
);
986 DPRINT1("MapBuffers: %d\n", PortConfig
->MapBuffers
);
987 DPRINT1("NeedPhysicalAddresses: %d\n", PortConfig
->NeedPhysicalAddresses
);
988 DPRINT1("TaggedQueuing: %d\n", PortConfig
->TaggedQueuing
);
989 DPRINT1("AutoRequestSense: %d\n", PortConfig
->AutoRequestSense
);
990 DPRINT1("MultipleRequestPerLu: %d\n", PortConfig
->MultipleRequestPerLu
);
991 DPRINT1("ReceiveEvent: %d\n", PortConfig
->ReceiveEvent
);
992 DPRINT1("RealModeInitialized: %d\n", PortConfig
->RealModeInitialized
);
993 DPRINT1("BufferAccessScsiPortControlled: %d\n", PortConfig
->BufferAccessScsiPortControlled
);
994 DPRINT1("MaximumNumberOfTargets: %d\n", PortConfig
->MaximumNumberOfTargets
);
995 DPRINT1("SlotNumber: %d\n", PortConfig
->SlotNumber
);
996 DPRINT1("BusInterruptLevel2: %x\n", PortConfig
->BusInterruptLevel2
);
997 DPRINT1("BusInterruptVector2: %x\n", PortConfig
->BusInterruptVector2
);
998 DPRINT1("InterruptMode2: %x\n", PortConfig
->InterruptMode2
);
999 DPRINT1("DmaChannel2: %d\n", PortConfig
->DmaChannel2
);
1000 DPRINT1("DmaPort2: %d\n", PortConfig
->DmaPort2
);
1001 DPRINT1("DmaWidth2: %d\n", PortConfig
->DmaWidth2
);
1002 DPRINT1("DmaSpeed2: %d\n", PortConfig
->DmaSpeed2
);
1003 DPRINT1("DeviceExtensionSize: %d\n", PortConfig
->DeviceExtensionSize
);
1004 DPRINT1("SpecificLuExtensionSize: %d\n", PortConfig
->SpecificLuExtensionSize
);
1005 DPRINT1("SrbExtensionSize: %d\n", PortConfig
->SrbExtensionSize
);
1009 if (DeviceExtension
->VirtualAddress
== NULL
&& DeviceExtension
->SrbExtensionSize
)
1011 ScsiPortGetUncachedExtension(&DeviceExtension
->MiniPortDeviceExtension
,
1016 /* Register an interrupt handler for this device */
1017 MappedIrq
= HalGetInterruptVector(PortConfig
->AdapterInterfaceType
,
1018 PortConfig
->SystemIoBusNumber
,
1019 PortConfig
->BusInterruptLevel
,
1023 * Something is wrong in our interrupt conecting code.
1024 * The promise Ultra100TX driver returns 0 for BusInterruptVector
1025 * and a nonzero value for BusInterruptLevel. The driver does only
1026 * work with this fix.
1028 PortConfig
->BusInterruptLevel
,
1030 PortConfig
->BusInterruptVector
,
1034 DPRINT("AdapterInterfaceType %x, SystemIoBusNumber %x, BusInterruptLevel %x, BusInterruptVector %x\n",
1035 PortConfig
->AdapterInterfaceType
, PortConfig
->SystemIoBusNumber
,
1036 PortConfig
->BusInterruptLevel
, PortConfig
->BusInterruptVector
);
1037 Status
= IoConnectInterrupt(&DeviceExtension
->Interrupt
,
1044 PortConfig
->InterruptMode
,
1048 if (!NT_SUCCESS(Status
))
1050 DbgPrint("Could not connect interrupt %d\n",
1051 PortConfig
->BusInterruptVector
);
1055 if (!(HwInitializationData
->HwInitialize
)(&DeviceExtension
->MiniPortDeviceExtension
))
1057 DbgPrint("HwInitialize() failed!");
1058 Status
= STATUS_UNSUCCESSFUL
;
1062 /* Initialize port capabilities */
1063 DeviceExtension
->PortCapabilities
= ExAllocatePool(NonPagedPool
,
1064 sizeof(IO_SCSI_CAPABILITIES
));
1065 if (DeviceExtension
->PortCapabilities
== NULL
)
1067 DbgPrint("Failed to allocate port capabilities!\n");
1068 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1072 PortCapabilities
= DeviceExtension
->PortCapabilities
;
1073 PortCapabilities
->Length
= sizeof(IO_SCSI_CAPABILITIES
);
1074 if (PortConfig
->ScatterGather
== FALSE
||
1075 PortConfig
->NumberOfPhysicalBreaks
>= (0x100000000LL
>> PAGE_SHIFT
) ||
1076 PortConfig
->MaximumTransferLength
< PortConfig
->NumberOfPhysicalBreaks
* PAGE_SIZE
)
1078 PortCapabilities
->MaximumTransferLength
=
1079 PortConfig
->MaximumTransferLength
;
1083 PortCapabilities
->MaximumTransferLength
=
1084 PortConfig
->NumberOfPhysicalBreaks
* PAGE_SIZE
;
1087 PortCapabilities
->MaximumPhysicalPages
=
1088 PortCapabilities
->MaximumTransferLength
/ PAGE_SIZE
;
1089 PortCapabilities
->SupportedAsynchronousEvents
= 0; /* FIXME */
1090 PortCapabilities
->AlignmentMask
=
1091 PortConfig
->AlignmentMask
;
1092 PortCapabilities
->TaggedQueuing
=
1093 PortConfig
->TaggedQueuing
;
1094 PortCapabilities
->AdapterScansDown
=
1095 PortConfig
->AdapterScansDown
;
1096 PortCapabilities
->AdapterUsesPio
= TRUE
; /* FIXME */
1098 /* Scan the adapter for devices */
1099 SpiScanAdapter (DeviceExtension
);
1101 /* Build the registry device map */
1102 SpiBuildDeviceMap (DeviceExtension
,
1103 (PUNICODE_STRING
)Argument2
);
1105 /* Create the dos device link */
1106 swprintf(DosNameBuffer
,
1108 SystemConfig
->ScsiPortCount
);
1109 RtlInitUnicodeString(&DosDeviceName
,
1111 IoCreateSymbolicLink(&DosDeviceName
,
1114 /* Update the system configuration info */
1115 if (PortConfig
->AtdiskPrimaryClaimed
== TRUE
)
1116 SystemConfig
->AtDiskPrimaryAddressClaimed
= TRUE
;
1117 if (PortConfig
->AtdiskSecondaryClaimed
== TRUE
)
1118 SystemConfig
->AtDiskSecondaryAddressClaimed
= TRUE
;
1120 SystemConfig
->ScsiPortCount
++;
1121 PortDeviceObject
= NULL
;
1126 DPRINT("HwFindAdapter() Result: %lu\n", Result
);
1128 ExFreePool (PortConfig
);
1129 IoDeleteDevice (PortDeviceObject
);
1130 PortDeviceObject
= NULL
;
1133 DPRINT("Bus: %lu MaxBus: %lu\n", BusNumber
, MaxBus
);
1134 if (BusNumber
>= MaxBus
)
1136 DPRINT("Scanned all buses!\n");
1137 Status
= STATUS_SUCCESS
;
1144 SlotNumber
.u
.AsULONG
= 0;
1149 /* Clean up the mess */
1150 if (PortDeviceObject
!= NULL
)
1152 DPRINT("Delete device: %p\n", PortDeviceObject
);
1154 DeviceExtension
= PortDeviceObject
->DeviceExtension
;
1156 if (DeviceExtension
->PortCapabilities
!= NULL
)
1158 IoDisconnectInterrupt (DeviceExtension
->Interrupt
);
1159 ExFreePool (DeviceExtension
->PortCapabilities
);
1162 if (DeviceExtension
->PortConfig
!= NULL
)
1164 ExFreePool (DeviceExtension
->PortConfig
);
1167 IoDeleteDevice (PortDeviceObject
);
1170 DPRINT("ScsiPortInitialize() done!\n");
1172 return (DeviceFound
== FALSE
) ? Status
: STATUS_SUCCESS
;
1180 ScsiPortIoMapTransfer(IN PVOID HwDeviceExtension
,
1181 IN PSCSI_REQUEST_BLOCK Srb
,
1182 IN ULONG LogicalAddress
,
1185 DPRINT1("ScsiPortIoMapTransfer()\n");
1194 ScsiPortLogError(IN PVOID HwDeviceExtension
,
1195 IN PSCSI_REQUEST_BLOCK Srb OPTIONAL
,
1202 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
1204 DPRINT1("ScsiPortLogError() called\n");
1206 DeviceExtension
= CONTAINING_RECORD(HwDeviceExtension
,
1207 SCSI_PORT_DEVICE_EXTENSION
,
1208 MiniPortDeviceExtension
);
1211 DPRINT("ScsiPortLogError() done\n");
1219 ScsiPortMoveMemory(OUT PVOID Destination
,
1223 RtlMoveMemory(Destination
,
1233 ScsiPortNotification(IN SCSI_NOTIFICATION_TYPE NotificationType
,
1234 IN PVOID HwDeviceExtension
,
1237 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
1240 DPRINT("ScsiPortNotification() called\n");
1242 DeviceExtension
= CONTAINING_RECORD(HwDeviceExtension
,
1243 SCSI_PORT_DEVICE_EXTENSION
,
1244 MiniPortDeviceExtension
);
1246 DPRINT("DeviceExtension %p\n", DeviceExtension
);
1248 va_start(ap
, HwDeviceExtension
);
1250 switch (NotificationType
)
1252 case RequestComplete
:
1254 PSCSI_REQUEST_BLOCK Srb
;
1256 Srb
= (PSCSI_REQUEST_BLOCK
) va_arg (ap
, PSCSI_REQUEST_BLOCK
);
1258 DPRINT("Notify: RequestComplete (Srb %p)\n", Srb
);
1259 DeviceExtension
->Flags
|= IRP_FLAG_COMPLETE
;
1260 Srb
->SrbFlags
&= ~SRB_FLAGS_IS_ACTIVE
;
1261 InterlockedIncrement((PLONG
)&DeviceExtension
->CompleteRequestCount
);
1266 DPRINT("Notify: NextRequest\n");
1267 DeviceExtension
->Flags
|= IRP_FLAG_NEXT
;
1268 InterlockedIncrement((PLONG
)&DeviceExtension
->NextRequestCount
);
1276 PSCSI_PORT_LUN_EXTENSION LunExtension
;
1278 PathId
= (UCHAR
) va_arg (ap
, int);
1279 TargetId
= (UCHAR
) va_arg (ap
, int);
1280 Lun
= (UCHAR
) va_arg (ap
, int);
1282 DPRINT ("Notify: NextLuRequest(PathId %u TargetId %u Lun %u)\n",
1283 PathId
, TargetId
, Lun
);
1285 LunExtension
= SpiGetLunExtension(DeviceExtension
,
1291 DeviceExtension
->Flags
|= IRP_FLAG_NEXT_LU
;
1292 InterlockedIncrement((PLONG
)&LunExtension
->NextLuRequestCount
);
1293 InterlockedIncrement((PLONG
)&DeviceExtension
->NextLuRequestCount
);
1299 DPRINT1("Notify: ResetDetected\n");
1304 DPRINT1 ("Unsupported notification %lu\n", NotificationType
);
1307 if (KeGetCurrentIrql() >= DISPATCH_LEVEL
)
1309 IoRequestDpc(DeviceExtension
->DeviceObject
,
1315 SpiProcessRequests(DeviceExtension
, NULL
);
1326 ScsiPortSetBusDataByOffset(IN PVOID DeviceExtension
,
1327 IN ULONG BusDataType
,
1328 IN ULONG SystemIoBusNumber
,
1329 IN ULONG SlotNumber
,
1334 DPRINT("ScsiPortSetBusDataByOffset()\n");
1335 return(HalSetBusDataByOffset(BusDataType
,
1348 ScsiPortValidateRange(IN PVOID HwDeviceExtension
,
1349 IN INTERFACE_TYPE BusType
,
1350 IN ULONG SystemIoBusNumber
,
1351 IN SCSI_PHYSICAL_ADDRESS IoAddress
,
1352 IN ULONG NumberOfBytes
,
1353 IN BOOLEAN InIoSpace
)
1355 DPRINT("ScsiPortValidateRange()\n");
1360 /* INTERNAL FUNCTIONS ********************************************************/
1364 SpiGetPciConfigData (IN
struct _HW_INITIALIZATION_DATA
*HwInitializationData
,
1365 IN OUT PPORT_CONFIGURATION_INFORMATION PortConfig
,
1367 IN OUT PPCI_SLOT_NUMBER NextSlotNumber
)
1369 PCI_COMMON_CONFIG PciConfig
;
1370 PCI_SLOT_NUMBER SlotNumber
;
1373 ULONG FunctionNumber
;
1374 CHAR VendorIdString
[8];
1375 CHAR DeviceIdString
[8];
1379 DPRINT ("SpiGetPciConfiguration() called\n");
1381 if (NextSlotNumber
->u
.bits
.FunctionNumber
>= PCI_MAX_FUNCTION
)
1383 NextSlotNumber
->u
.bits
.FunctionNumber
= 0;
1384 NextSlotNumber
->u
.bits
.DeviceNumber
++;
1387 if (NextSlotNumber
->u
.bits
.DeviceNumber
>= PCI_MAX_DEVICES
)
1389 NextSlotNumber
->u
.bits
.DeviceNumber
= 0;
1393 for (DeviceNumber
= NextSlotNumber
->u
.bits
.DeviceNumber
; DeviceNumber
< PCI_MAX_DEVICES
; DeviceNumber
++)
1395 SlotNumber
.u
.bits
.DeviceNumber
= DeviceNumber
;
1397 for (FunctionNumber
= NextSlotNumber
->u
.bits
.FunctionNumber
; FunctionNumber
< PCI_MAX_FUNCTION
; FunctionNumber
++)
1399 SlotNumber
.u
.bits
.FunctionNumber
= FunctionNumber
;
1401 DataSize
= HalGetBusData (PCIConfiguration
,
1403 SlotNumber
.u
.AsULONG
,
1405 PCI_COMMON_HDR_LENGTH
);
1406 if (DataSize
!= PCI_COMMON_HDR_LENGTH
)
1408 if (FunctionNumber
== 0)
1418 sprintf (VendorIdString
, "%04hx", PciConfig
.VendorID
);
1419 sprintf (DeviceIdString
, "%04hx", PciConfig
.DeviceID
);
1421 if (!_strnicmp(VendorIdString
, HwInitializationData
->VendorId
, HwInitializationData
->VendorIdLength
) &&
1422 !_strnicmp(DeviceIdString
, HwInitializationData
->DeviceId
, HwInitializationData
->DeviceIdLength
))
1424 DPRINT ("Found device 0x%04hx 0x%04hx at %1lu %2lu %1lu\n",
1428 SlotNumber
.u
.bits
.DeviceNumber
,
1429 SlotNumber
.u
.bits
.FunctionNumber
);
1431 PortConfig
->BusInterruptLevel
=
1432 PortConfig
->BusInterruptVector
= PciConfig
.u
.type0
.InterruptLine
;
1433 PortConfig
->SlotNumber
= SlotNumber
.u
.AsULONG
;
1435 /* Initialize access ranges */
1436 if (PortConfig
->NumberOfAccessRanges
> 0)
1438 if (PortConfig
->NumberOfAccessRanges
> PCI_TYPE0_ADDRESSES
)
1439 PortConfig
->NumberOfAccessRanges
= PCI_TYPE0_ADDRESSES
;
1441 for (i
= 0; i
< PortConfig
->NumberOfAccessRanges
; i
++)
1443 PortConfig
->AccessRanges
[i
].RangeStart
.QuadPart
=
1444 PciConfig
.u
.type0
.BaseAddresses
[i
] & PCI_ADDRESS_IO_ADDRESS_MASK
;
1445 if (PortConfig
->AccessRanges
[i
].RangeStart
.QuadPart
!= 0)
1447 RangeLength
= (ULONG
)-1;
1448 HalSetBusDataByOffset (PCIConfiguration
,
1450 SlotNumber
.u
.AsULONG
,
1451 (PVOID
)&RangeLength
,
1452 0x10 + (i
* sizeof(ULONG
)),
1455 HalGetBusDataByOffset (PCIConfiguration
,
1457 SlotNumber
.u
.AsULONG
,
1458 (PVOID
)&RangeLength
,
1459 0x10 + (i
* sizeof(ULONG
)),
1462 HalSetBusDataByOffset (PCIConfiguration
,
1464 SlotNumber
.u
.AsULONG
,
1465 (PVOID
)&PciConfig
.u
.type0
.BaseAddresses
[i
],
1466 0x10 + (i
* sizeof(ULONG
)),
1468 if (RangeLength
!= 0)
1470 PortConfig
->AccessRanges
[i
].RangeLength
=
1471 -(RangeLength
& PCI_ADDRESS_IO_ADDRESS_MASK
);
1472 PortConfig
->AccessRanges
[i
].RangeInMemory
=
1473 !(PciConfig
.u
.type0
.BaseAddresses
[i
] & PCI_ADDRESS_IO_SPACE
);
1475 DPRINT("RangeStart 0x%lX RangeLength 0x%lX RangeInMemory %s\n",
1476 PciConfig
.u
.type0
.BaseAddresses
[i
] & PCI_ADDRESS_IO_ADDRESS_MASK
,
1477 -(RangeLength
& PCI_ADDRESS_IO_ADDRESS_MASK
),
1478 (PciConfig
.u
.type0
.BaseAddresses
[i
] & PCI_ADDRESS_IO_SPACE
)?"FALSE":"TRUE");
1484 NextSlotNumber
->u
.bits
.DeviceNumber
= DeviceNumber
;
1485 NextSlotNumber
->u
.bits
.FunctionNumber
= FunctionNumber
;
1487 PortConfig
->SlotNumber
= NextSlotNumber
->u
.AsULONG
;
1489 NextSlotNumber
->u
.bits
.FunctionNumber
+= 1;
1495 if (FunctionNumber
== 0 && !(PciConfig
.HeaderType
& PCI_MULTIFUNCTION
))
1500 NextSlotNumber
->u
.bits
.FunctionNumber
= 0;
1503 DPRINT ("No device found\n");
1510 /**********************************************************************
1512 * ScsiPortCreateClose
1515 * Answer requests for Create/Close calls: a null operation.
1522 * Pointer to a device object.
1525 * Pointer to an IRP.
1531 static NTSTATUS STDCALL
1532 ScsiPortCreateClose(IN PDEVICE_OBJECT DeviceObject
,
1535 DPRINT("ScsiPortCreateClose()\n");
1537 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1538 Irp
->IoStatus
.Information
= FILE_OPENED
;
1540 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1542 return(STATUS_SUCCESS
);
1546 /**********************************************************************
1548 * ScsiPortDispatchScsi
1551 * Answer requests for SCSI calls
1557 * Standard dispatch arguments
1563 static NTSTATUS STDCALL
1564 ScsiPortDispatchScsi(IN PDEVICE_OBJECT DeviceObject
,
1567 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
1568 PSCSI_PORT_LUN_EXTENSION LunExtension
;
1569 PIO_STACK_LOCATION Stack
;
1570 PSCSI_REQUEST_BLOCK Srb
;
1571 NTSTATUS Status
= STATUS_SUCCESS
;
1574 DPRINT("ScsiPortDispatchScsi(DeviceObject %p Irp %p)\n",
1577 DeviceExtension
= DeviceObject
->DeviceExtension
;
1578 Stack
= IoGetCurrentIrpStackLocation(Irp
);
1580 Srb
= Stack
->Parameters
.Scsi
.Srb
;
1583 Status
= STATUS_UNSUCCESSFUL
;
1585 Irp
->IoStatus
.Status
= Status
;
1586 Irp
->IoStatus
.Information
= 0;
1588 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1593 DPRINT("Srb: %p\n", Srb
);
1594 DPRINT("Srb->Function: %lu\n", Srb
->Function
);
1595 DPRINT("PathId: %lu TargetId: %lu Lun: %lu\n", Srb
->PathId
, Srb
->TargetId
, Srb
->Lun
);
1597 LunExtension
= SpiGetLunExtension(DeviceExtension
,
1601 if (LunExtension
== NULL
)
1603 Status
= STATUS_NO_SUCH_DEVICE
;
1605 Srb
->SrbStatus
= SRB_STATUS_NO_DEVICE
;
1606 Irp
->IoStatus
.Status
= Status
;
1607 Irp
->IoStatus
.Information
= 0;
1609 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1614 switch (Srb
->Function
)
1616 case SRB_FUNCTION_EXECUTE_SCSI
:
1617 case SRB_FUNCTION_IO_CONTROL
:
1618 IoMarkIrpPending(Irp
);
1619 Srb
->OriginalRequest
= LunExtension
;
1620 Irp
->Tail
.Overlay
.DriverContext
[3] = Srb
;
1621 SpiProcessRequests(DeviceExtension
, Irp
);
1622 return(STATUS_PENDING
);
1624 case SRB_FUNCTION_SHUTDOWN
:
1625 case SRB_FUNCTION_FLUSH
:
1626 if (DeviceExtension
->PortConfig
->CachesData
== TRUE
)
1628 IoMarkIrpPending(Irp
);
1629 Srb
->OriginalRequest
= LunExtension
;
1630 Irp
->Tail
.Overlay
.DriverContext
[3] = Srb
;
1631 SpiProcessRequests(DeviceExtension
, Irp
);
1632 return(STATUS_PENDING
);
1636 case SRB_FUNCTION_CLAIM_DEVICE
:
1637 DPRINT (" SRB_FUNCTION_CLAIM_DEVICE\n");
1639 /* Reference device object and keep the device object */
1640 ObReferenceObject(DeviceObject
);
1641 LunExtension
->DeviceObject
= DeviceObject
;
1642 LunExtension
->DeviceClaimed
= TRUE
;
1643 Srb
->DataBuffer
= DeviceObject
;
1646 case SRB_FUNCTION_RELEASE_DEVICE
:
1647 DPRINT (" SRB_FUNCTION_RELEASE_DEVICE\n");
1648 DPRINT ("PathId: %lu TargetId: %lu Lun: %lu\n",
1649 Srb
->PathId
, Srb
->TargetId
, Srb
->Lun
);
1651 /* Dereference device object and clear the device object */
1652 ObDereferenceObject(LunExtension
->DeviceObject
);
1653 LunExtension
->DeviceObject
= NULL
;
1654 LunExtension
->DeviceClaimed
= FALSE
;
1658 DPRINT1("SRB function not implemented (Function %lu)\n", Srb
->Function
);
1659 Status
= STATUS_NOT_IMPLEMENTED
;
1663 Irp
->IoStatus
.Status
= Status
;
1664 Irp
->IoStatus
.Information
= DataSize
;
1666 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1672 /**********************************************************************
1674 * ScsiPortDeviceControl
1677 * Answer requests for device control calls
1683 * Standard dispatch arguments
1689 static NTSTATUS STDCALL
1690 ScsiPortDeviceControl(IN PDEVICE_OBJECT DeviceObject
,
1693 PIO_STACK_LOCATION Stack
;
1694 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
1696 DPRINT("ScsiPortDeviceControl()\n");
1698 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1699 Irp
->IoStatus
.Information
= 0;
1702 Stack
= IoGetCurrentIrpStackLocation(Irp
);
1703 DeviceExtension
= DeviceObject
->DeviceExtension
;
1705 switch (Stack
->Parameters
.DeviceIoControl
.IoControlCode
)
1707 case IOCTL_SCSI_GET_DUMP_POINTERS
:
1709 PDUMP_POINTERS DumpPointers
;
1710 DPRINT(" IOCTL_SCSI_GET_DUMP_POINTERS\n");
1711 DumpPointers
= (PDUMP_POINTERS
)Irp
->AssociatedIrp
.SystemBuffer
;
1712 DumpPointers
->DeviceObject
= DeviceObject
;
1714 Irp
->IoStatus
.Information
= sizeof(DUMP_POINTERS
);
1718 case IOCTL_SCSI_GET_CAPABILITIES
:
1720 DPRINT(" IOCTL_SCSI_GET_CAPABILITIES\n");
1722 *((PIO_SCSI_CAPABILITIES
*)Irp
->AssociatedIrp
.SystemBuffer
) =
1723 DeviceExtension
->PortCapabilities
;
1725 Irp
->IoStatus
.Information
= sizeof(PIO_SCSI_CAPABILITIES
);
1729 case IOCTL_SCSI_GET_INQUIRY_DATA
:
1731 DPRINT(" IOCTL_SCSI_GET_INQUIRY_DATA\n");
1733 /* Copy inquiry data to the port device extension */
1734 Irp
->IoStatus
.Information
=
1735 SpiGetInquiryData(DeviceExtension
,
1736 Irp
->AssociatedIrp
.SystemBuffer
);
1737 DPRINT("Inquiry data size: %lu\n", Irp
->IoStatus
.Information
);
1742 DPRINT1(" unknown ioctl code: 0x%lX\n",
1743 Stack
->Parameters
.DeviceIoControl
.IoControlCode
);
1747 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1749 return(STATUS_SUCCESS
);
1753 SpiAllocateSrbExtension(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
1754 PSCSI_REQUEST_BLOCK Srb
)
1759 DPRINT("SpiAllocateSrbExtension\n");
1761 DPRINT("DeviceExtension->VirtualAddress %x, DeviceExtension->SrbExtensionSize %x\n",
1762 DeviceExtension
->VirtualAddress
, DeviceExtension
->SrbExtensionSize
);
1764 if (DeviceExtension
->VirtualAddress
!= NULL
&&
1765 DeviceExtension
->SrbExtensionSize
> 0)
1767 for (i
= 0, mask
= 1; i
< MAX_SRB_EXTENSIONS
; i
++, mask
<<= 1)
1769 if (!(DeviceExtension
->VirtualAddressMap
& mask
))
1771 DeviceExtension
->VirtualAddressMap
|= mask
;
1772 Srb
->SrbExtension
= DeviceExtension
->VirtualAddress
+ i
* DeviceExtension
->SrbExtensionSize
;
1773 DPRINT("%x\n", Srb
->SrbExtension
);
1778 Srb
->SrbExtension
= NULL
;
1782 SpiFreeSrbExtension(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
1783 PSCSI_REQUEST_BLOCK Srb
)
1787 if (DeviceExtension
->VirtualAddress
!= NULL
&&
1788 DeviceExtension
->SrbExtensionSize
> 0 &&
1789 Srb
->SrbExtension
!= NULL
)
1791 i
= ((ULONG_PTR
)Srb
->SrbExtension
- (ULONG_PTR
)DeviceExtension
->VirtualAddress
) / DeviceExtension
->SrbExtensionSize
;
1792 DeviceExtension
->VirtualAddressMap
&= ~(1 << i
);
1794 Srb
->SrbExtension
= NULL
;
1798 static BOOLEAN STDCALL
1799 ScsiPortStartPacket(IN OUT PVOID Context
)
1801 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
1802 PSCSI_REQUEST_BLOCK Srb
;
1804 PIO_STACK_LOCATION IrpStack
;
1806 DPRINT("ScsiPortStartPacket() called\n");
1808 Srb
= (PSCSI_REQUEST_BLOCK
)Context
;
1809 Irp
= (PIRP
)Srb
->OriginalRequest
;
1810 IrpStack
= IoGetCurrentIrpStackLocation(Irp
);
1811 DeviceExtension
= IrpStack
->DeviceObject
->DeviceExtension
;
1813 return(DeviceExtension
->HwStartIo(&DeviceExtension
->MiniPortDeviceExtension
,
1818 static PSCSI_PORT_LUN_EXTENSION
1819 SpiAllocateLunExtension (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
1824 PSCSI_PORT_LUN_EXTENSION LunExtension
;
1825 ULONG LunExtensionSize
;
1827 DPRINT("SpiAllocateLunExtension (%p %u %u %u)\n",
1828 DeviceExtension
, PathId
, TargetId
, Lun
);
1831 sizeof(SCSI_PORT_LUN_EXTENSION
) + DeviceExtension
->LunExtensionSize
;
1832 DPRINT("LunExtensionSize %lu\n", LunExtensionSize
);
1834 LunExtension
= ExAllocatePool(NonPagedPool
,
1836 if (LunExtension
== NULL
)
1841 RtlZeroMemory(LunExtension
,
1844 InsertTailList(&DeviceExtension
->LunExtensionListHead
,
1845 &LunExtension
->List
);
1847 LunExtension
->PathId
= PathId
;
1848 LunExtension
->TargetId
= TargetId
;
1849 LunExtension
->Lun
= Lun
;
1851 LunExtension
->PendingIrpCount
= 0;
1852 LunExtension
->ActiveIrpCount
= 0;
1854 LunExtension
->NextIrp
= NULL
;
1856 return LunExtension
;
1861 SpiRemoveLunExtension (IN PSCSI_PORT_LUN_EXTENSION LunExtension
)
1863 DPRINT("SpiRemoveLunExtension(%p) called\n",
1866 if (LunExtension
== NULL
)
1869 RemoveEntryList (&LunExtension
->List
);
1872 /* Release LUN extersion data */
1875 ExFreePool (LunExtension
);
1881 static PSCSI_PORT_LUN_EXTENSION
1882 SpiGetLunExtension (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
1887 PSCSI_PORT_LUN_EXTENSION LunExtension
;
1890 DPRINT("SpiGetLunExtension(%p %u %u %u) called\n",
1891 DeviceExtension
, PathId
, TargetId
, Lun
);
1893 if (IsListEmpty(&DeviceExtension
->LunExtensionListHead
))
1896 Entry
= DeviceExtension
->LunExtensionListHead
.Flink
;
1897 while (Entry
!= &DeviceExtension
->LunExtensionListHead
)
1899 LunExtension
= CONTAINING_RECORD(Entry
,
1900 SCSI_PORT_LUN_EXTENSION
,
1902 if (LunExtension
->PathId
== PathId
&&
1903 LunExtension
->TargetId
== TargetId
&&
1904 LunExtension
->Lun
== Lun
)
1906 return LunExtension
;
1909 Entry
= Entry
->Flink
;
1917 SpiSendInquiry (IN PDEVICE_OBJECT DeviceObject
,
1918 IN OUT PSCSI_REQUEST_BLOCK Srb
,
1919 IN OUT PIO_STATUS_BLOCK IoStatusBlock
,
1920 IN OUT PKEVENT Event
)
1922 PIO_STACK_LOCATION IrpStack
;
1926 DPRINT ("SpiSendInquiry() called\n");
1929 KeInitializeEvent (Event
,
1933 Irp
= IoBuildDeviceIoControlRequest (IOCTL_SCSI_EXECUTE_OUT
,
1938 Srb
->DataTransferLength
,
1944 DPRINT("IoBuildDeviceIoControlRequest() failed\n");
1945 return STATUS_INSUFFICIENT_RESOURCES
;
1948 /* Attach Srb to the Irp */
1949 IrpStack
= IoGetNextIrpStackLocation (Irp
);
1950 IrpStack
->Parameters
.Scsi
.Srb
= Srb
;
1951 Srb
->OriginalRequest
= Irp
;
1953 /* Call the driver */
1954 Status
= IoCallDriver (DeviceObject
,
1961 SpiScanAdapter (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
)
1963 PSCSI_REQUEST_BLOCK Srb
;
1967 PSCSI_PORT_SCAN_ADAPTER ScanDataArray
;
1968 PSCSI_PORT_SCAN_ADAPTER ScanData
;
1974 PKWAIT_BLOCK WaitBlockArray
;
1976 DPRINT ("SpiScanAdapter() called\n");
1978 MaxCount
= DeviceExtension
->PortConfig
->NumberOfBuses
*
1979 DeviceExtension
->PortConfig
->MaximumNumberOfTargets
;
1981 ScanDataArray
= ExAllocatePool(NonPagedPool
, MaxCount
* (sizeof(SCSI_PORT_SCAN_ADAPTER
) + sizeof(PVOID
) + sizeof(KWAIT_BLOCK
)));
1982 if (ScanDataArray
== NULL
)
1986 EventArray
= (PVOID
*)((PUCHAR
)ScanDataArray
+ MaxCount
* sizeof(SCSI_PORT_SCAN_ADAPTER
));
1987 WaitBlockArray
= (PKWAIT_BLOCK
)((PUCHAR
)EventArray
+ MaxCount
* sizeof(PVOID
));
1989 for (Bus
= 0; Bus
< DeviceExtension
->PortConfig
->NumberOfBuses
; Bus
++)
1991 for (Target
= 0; Target
< DeviceExtension
->PortConfig
->MaximumNumberOfTargets
; Target
++)
1993 ScanData
= &ScanDataArray
[Bus
* DeviceExtension
->PortConfig
->MaximumNumberOfTargets
+ Target
];
1994 ScanData
->Bus
= Bus
;
1995 ScanData
->Target
= Target
;
1997 ScanData
->Active
= FALSE
;
2004 for (i
= 0; i
< MaxCount
; i
++)
2006 ScanData
= &ScanDataArray
[i
];
2007 Srb
= &ScanData
->Srb
;
2008 if (ScanData
->Active
)
2010 if (ScanData
->Status
== STATUS_PENDING
&&
2011 0 == KeReadStateEvent(&ScanData
->Event
))
2018 ScanData
->Status
= ScanData
->IoStatusBlock
.Status
;
2020 ScanData
->Active
= FALSE
;
2021 DPRINT ("Target %lu Lun %lu\n", ScanData
->Target
, ScanData
->Lun
);
2022 DPRINT ("Status %lx Srb.SrbStatus %x\n", ScanData
->Status
, Srb
->SrbStatus
);
2023 DPRINT ("DeviceTypeQualifier %x\n", ((PINQUIRYDATA
)Srb
->DataBuffer
)->DeviceTypeQualifier
);
2025 if (NT_SUCCESS(ScanData
->Status
) &&
2026 (Srb
->SrbStatus
== SRB_STATUS_SUCCESS
||
2027 Srb
->SrbStatus
== SRB_STATUS_DATA_OVERRUN
) &&
2028 ((PINQUIRYDATA
)Srb
->DataBuffer
)->DeviceTypeQualifier
== 0)
2030 /* Copy inquiry data */
2031 RtlCopyMemory (&ScanData
->LunExtension
->InquiryData
,
2033 sizeof(INQUIRYDATA
));
2038 SpiRemoveLunExtension (ScanData
->LunExtension
);
2039 ScanData
->Lun
= SCSI_MAXIMUM_LOGICAL_UNITS
;
2042 if (ScanData
->Lun
>= SCSI_MAXIMUM_LOGICAL_UNITS
)
2046 RtlZeroMemory(Srb
, sizeof(SCSI_REQUEST_BLOCK
));
2047 Srb
->SrbFlags
= SRB_FLAGS_DATA_IN
;
2048 Srb
->DataBuffer
= ScanData
->DataBuffer
;
2049 Srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
2050 Srb
->DataTransferLength
= 255; //256;
2052 Srb
->Lun
= ScanData
->Lun
;
2053 Srb
->PathId
= ScanData
->Bus
;
2054 Srb
->TargetId
= ScanData
->Target
;
2055 Srb
->SrbStatus
= SRB_STATUS_SUCCESS
;
2056 Cdb
= (PCDB
) &Srb
->Cdb
;
2058 Cdb
->CDB6INQUIRY
.OperationCode
= SCSIOP_INQUIRY
;
2059 Cdb
->CDB6INQUIRY
.AllocationLength
= 255;
2060 Cdb
->CDB6INQUIRY
.LogicalUnitNumber
= ScanData
->Lun
;
2062 RtlZeroMemory(Srb
->DataBuffer
, 256);
2064 ScanData
->LunExtension
= SpiAllocateLunExtension (DeviceExtension
,
2068 if (ScanData
->LunExtension
== NULL
)
2070 DPRINT1("Failed to allocate the LUN extension!\n");
2071 ScanData
->Lun
= SCSI_MAXIMUM_LOGICAL_UNITS
;
2074 ScanData
->Status
= SpiSendInquiry (DeviceExtension
->DeviceObject
,
2076 &ScanData
->IoStatusBlock
,
2078 ScanData
->Active
= TRUE
;
2080 if (ScanData
->Status
== STATUS_PENDING
)
2082 EventArray
[WaitCount
] = &ScanData
->Event
;
2086 if (WaitCount
> 0 && WaitCount
== ActiveCount
)
2088 KeWaitForMultipleObjects(WaitCount
,
2098 while (ActiveCount
> 0);
2100 ExFreePool(ScanDataArray
);
2102 DPRINT ("SpiScanAdapter() done\n");
2107 SpiGetInquiryData(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
2108 OUT PSCSI_ADAPTER_BUS_INFO AdapterBusInfo
)
2110 PSCSI_PORT_LUN_EXTENSION LunExtension
;
2111 PSCSI_INQUIRY_DATA UnitInfo
, PrevUnit
;
2117 DPRINT("SpiGetInquiryData() called\n");
2119 /* Copy inquiry data to the port device extension */
2120 AdapterBusInfo
->NumberOfBuses
= DeviceExtension
->PortConfig
->NumberOfBuses
;
2122 UnitInfo
= (PSCSI_INQUIRY_DATA
)
2123 ((PUCHAR
)AdapterBusInfo
+ sizeof(SCSI_ADAPTER_BUS_INFO
) +
2124 (sizeof(SCSI_BUS_DATA
) * (AdapterBusInfo
->NumberOfBuses
- 1)));
2126 for (Bus
= 0; Bus
< AdapterBusInfo
->NumberOfBuses
; Bus
++)
2128 AdapterBusInfo
->BusData
[Bus
].InitiatorBusId
=
2129 DeviceExtension
->PortConfig
->InitiatorBusId
[Bus
];
2130 AdapterBusInfo
->BusData
[Bus
].InquiryDataOffset
=
2131 (ULONG
)((PUCHAR
)UnitInfo
- (PUCHAR
)AdapterBusInfo
);
2136 for (Target
= 0; Target
< DeviceExtension
->PortConfig
->MaximumNumberOfTargets
; Target
++)
2138 for (Lun
= 0; Lun
< SCSI_MAXIMUM_LOGICAL_UNITS
; Lun
++)
2140 LunExtension
= SpiGetLunExtension(DeviceExtension
,
2144 if (LunExtension
!= NULL
)
2146 DPRINT("(Bus %lu Target %lu Lun %lu)\n",
2149 UnitInfo
->PathId
= Bus
;
2150 UnitInfo
->TargetId
= Target
;
2151 UnitInfo
->Lun
= Lun
;
2152 UnitInfo
->InquiryDataLength
= INQUIRYDATABUFFERSIZE
;
2153 RtlCopyMemory (&UnitInfo
->InquiryData
,
2154 &LunExtension
->InquiryData
,
2155 INQUIRYDATABUFFERSIZE
);
2156 if (PrevUnit
!= NULL
)
2158 PrevUnit
->NextInquiryDataOffset
=
2159 (ULONG
)((ULONG_PTR
)UnitInfo
-(ULONG_PTR
)AdapterBusInfo
);
2161 PrevUnit
= UnitInfo
;
2162 UnitInfo
= (PSCSI_INQUIRY_DATA
)((PUCHAR
)UnitInfo
+ sizeof(SCSI_INQUIRY_DATA
)+INQUIRYDATABUFFERSIZE
-1);
2167 DPRINT("UnitCount: %lu\n", UnitCount
);
2168 AdapterBusInfo
->BusData
[Bus
].NumberOfLogicalUnits
= UnitCount
;
2171 AdapterBusInfo
->BusData
[Bus
].InquiryDataOffset
= 0;
2175 DPRINT("Data size: %lu\n", (ULONG
)UnitInfo
- (ULONG
)AdapterBusInfo
);
2177 return (ULONG
)((PUCHAR
)UnitInfo
-(PUCHAR
)AdapterBusInfo
);
2181 static BOOLEAN STDCALL
2182 ScsiPortIsr(IN PKINTERRUPT Interrupt
,
2183 IN PVOID ServiceContext
)
2185 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
2187 DPRINT("ScsiPortIsr() called!\n");
2189 DeviceExtension
= (PSCSI_PORT_DEVICE_EXTENSION
)ServiceContext
;
2191 return DeviceExtension
->HwInterrupt(&DeviceExtension
->MiniPortDeviceExtension
);
2202 // IN PDEVICE_OBJECT DpcDeviceObject
2204 // IN PVOID DpcContext
2207 ScsiPortDpc(IN PKDPC Dpc
,
2208 IN PDEVICE_OBJECT DpcDeviceObject
,
2210 IN PVOID DpcContext
)
2212 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
2214 DPRINT("ScsiPortDpc(Dpc %p DpcDeviceObject %p DpcIrp %p DpcContext %p)\n",
2215 Dpc
, DpcDeviceObject
, DpcIrp
, DpcContext
);
2217 DeviceExtension
= (PSCSI_PORT_DEVICE_EXTENSION
)DpcContext
;
2219 SpiProcessRequests(DeviceExtension
, NULL
);
2221 DPRINT("ScsiPortDpc() done\n");
2227 // This function handles timeouts and other time delayed processing
2232 // IN PDEVICE_OBJECT DeviceObject Device object registered with timer
2233 // IN PVOID Context the Controller extension for the
2234 // controller the device is on
2237 ScsiPortIoTimer(PDEVICE_OBJECT DeviceObject
,
2240 DPRINT1("ScsiPortIoTimer()\n");
2244 static PSCSI_REQUEST_BLOCK
2245 ScsiPortInitSenseRequestSrb(PSCSI_REQUEST_BLOCK OriginalSrb
)
2247 PSCSI_REQUEST_BLOCK Srb
;
2251 Length
= sizeof(SCSI_REQUEST_BLOCK
) + sizeof(SENSE_DATA
) + 32;
2252 Srb
= ExAllocatePoolWithTag(NonPagedPool
,
2254 TAG('S', 'S', 'r', 'b'));
2260 RtlZeroMemory(Srb
, Length
);
2262 Srb
->PathId
= OriginalSrb
->PathId
;
2263 Srb
->TargetId
= OriginalSrb
->TargetId
;
2264 Srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
2265 Srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
2266 Srb
->SrbFlags
= SRB_FLAGS_DATA_IN
| SRB_FLAGS_DISABLE_SYNCH_TRANSFER
;
2267 Srb
->OriginalRequest
= OriginalSrb
->OriginalRequest
;
2269 Srb
->TimeOutValue
= 4;
2272 /* The DataBuffer must be located in contiguous physical memory if
2273 * the miniport driver uses dma for the sense info. The size of
2274 * the sense data is 18 byte. If the buffer starts at a 32 byte
2275 * boundary than is the buffer always in one memory page.
2277 Srb
->DataBuffer
= (PVOID
)ROUND_UP((ULONG_PTR
)(Srb
+ 1), 32);
2278 Srb
->DataTransferLength
= sizeof(SENSE_DATA
);
2280 Cdb
= (PCDB
)Srb
->Cdb
;
2281 Cdb
->CDB6INQUIRY
.OperationCode
= SCSIOP_REQUEST_SENSE
;
2282 Cdb
->CDB6INQUIRY
.AllocationLength
= sizeof(SENSE_DATA
);
2287 /**********************************************************************
2292 * Builds the registry device map of all device which are attached
2293 * to the given SCSI HBA port. The device map is located at:
2294 * \Registry\Machine\DeviceMap\Scsi
2304 * Name of registry driver service key.
2311 SpiBuildDeviceMap (PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
2312 PUNICODE_STRING RegistryPath
)
2314 PSCSI_PORT_LUN_EXTENSION LunExtension
;
2315 OBJECT_ATTRIBUTES ObjectAttributes
;
2316 UNICODE_STRING KeyName
;
2317 UNICODE_STRING ValueName
;
2318 WCHAR NameBuffer
[64];
2321 HANDLE ScsiPortKey
= NULL
;
2322 HANDLE ScsiBusKey
= NULL
;
2323 HANDLE ScsiInitiatorKey
= NULL
;
2324 HANDLE ScsiTargetKey
= NULL
;
2325 HANDLE ScsiLunKey
= NULL
;
2328 ULONG CurrentTarget
;
2335 DPRINT("SpiBuildDeviceMap() called\n");
2337 if (DeviceExtension
== NULL
|| RegistryPath
== NULL
)
2339 DPRINT1("Invalid parameter\n");
2340 return(STATUS_INVALID_PARAMETER
);
2343 /* Open or create the 'Scsi' subkey */
2344 RtlRosInitUnicodeStringFromLiteral(&KeyName
,
2345 L
"\\Registry\\Machine\\Hardware\\DeviceMap\\Scsi");
2346 InitializeObjectAttributes(&ObjectAttributes
,
2348 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
,
2351 Status
= ZwCreateKey(&ScsiKey
,
2356 REG_OPTION_VOLATILE
,
2358 if (!NT_SUCCESS(Status
))
2360 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status
);
2364 /* Create new 'Scsi Port X' subkey */
2365 DPRINT("Scsi Port %lu\n",
2366 DeviceExtension
->PortNumber
);
2368 swprintf(NameBuffer
,
2370 DeviceExtension
->PortNumber
);
2371 RtlInitUnicodeString(&KeyName
,
2373 InitializeObjectAttributes(&ObjectAttributes
,
2378 Status
= ZwCreateKey(&ScsiPortKey
,
2383 REG_OPTION_VOLATILE
,
2386 if (!NT_SUCCESS(Status
))
2388 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status
);
2393 * Create port-specific values
2396 /* Set 'DMA Enabled' (REG_DWORD) value */
2397 UlongData
= (ULONG
)!DeviceExtension
->PortCapabilities
->AdapterUsesPio
;
2398 DPRINT(" DMA Enabled = %s\n", (UlongData
) ? "TRUE" : "FALSE");
2399 RtlInitUnicodeString(&ValueName
,
2401 Status
= ZwSetValueKey(ScsiPortKey
,
2407 if (!NT_SUCCESS(Status
))
2409 DPRINT("ZwSetValueKey('DMA Enabled') failed (Status %lx)\n", Status
);
2410 ZwClose(ScsiPortKey
);
2414 /* Set 'Driver' (REG_SZ) value */
2415 DriverName
= wcsrchr(RegistryPath
->Buffer
, L
'\\') + 1;
2416 RtlInitUnicodeString(&ValueName
,
2418 Status
= ZwSetValueKey(ScsiPortKey
,
2423 (wcslen(DriverName
) + 1) * sizeof(WCHAR
));
2424 if (!NT_SUCCESS(Status
))
2426 DPRINT("ZwSetValueKey('Driver') failed (Status %lx)\n", Status
);
2427 ZwClose(ScsiPortKey
);
2431 /* Set 'Interrupt' (REG_DWORD) value (NT4 only) */
2432 UlongData
= (ULONG
)DeviceExtension
->PortConfig
->BusInterruptLevel
;
2433 DPRINT(" Interrupt = %lu\n", UlongData
);
2434 RtlInitUnicodeString(&ValueName
,
2436 Status
= ZwSetValueKey(ScsiPortKey
,
2442 if (!NT_SUCCESS(Status
))
2444 DPRINT("ZwSetValueKey('Interrupt') failed (Status %lx)\n", Status
);
2445 ZwClose(ScsiPortKey
);
2449 /* Set 'IOAddress' (REG_DWORD) value (NT4 only) */
2450 UlongData
= ScsiPortConvertPhysicalAddressToUlong(DeviceExtension
->PortConfig
->AccessRanges
[0].RangeStart
);
2451 DPRINT(" IOAddress = %lx\n", UlongData
);
2452 RtlInitUnicodeString(&ValueName
,
2454 Status
= ZwSetValueKey(ScsiPortKey
,
2460 if (!NT_SUCCESS(Status
))
2462 DPRINT("ZwSetValueKey('IOAddress') failed (Status %lx)\n", Status
);
2463 ZwClose(ScsiPortKey
);
2467 /* Enumerate buses */
2468 for (BusNumber
= 0; BusNumber
< DeviceExtension
->PortConfig
->NumberOfBuses
; BusNumber
++)
2470 /* Create 'Scsi Bus X' key */
2471 DPRINT(" Scsi Bus %lu\n", BusNumber
);
2472 swprintf(NameBuffer
,
2475 RtlInitUnicodeString(&KeyName
,
2477 InitializeObjectAttributes(&ObjectAttributes
,
2482 Status
= ZwCreateKey(&ScsiBusKey
,
2487 REG_OPTION_VOLATILE
,
2489 if (!NT_SUCCESS(Status
))
2491 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status
);
2495 /* Create 'Initiator Id X' key */
2496 DPRINT(" Initiator Id %u\n",
2497 DeviceExtension
->PortConfig
->InitiatorBusId
[BusNumber
]);
2498 swprintf(NameBuffer
,
2500 (unsigned int)(UCHAR
)DeviceExtension
->PortConfig
->InitiatorBusId
[BusNumber
]);
2501 RtlInitUnicodeString(&KeyName
,
2503 InitializeObjectAttributes(&ObjectAttributes
,
2508 Status
= ZwCreateKey(&ScsiInitiatorKey
,
2513 REG_OPTION_VOLATILE
,
2515 if (!NT_SUCCESS(Status
))
2517 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status
);
2521 /* FIXME: Are there any initiator values (??) */
2523 ZwClose(ScsiInitiatorKey
);
2524 ScsiInitiatorKey
= NULL
;
2527 /* Enumerate targets */
2528 CurrentTarget
= (ULONG
)-1;
2529 ScsiTargetKey
= NULL
;
2530 for (Target
= 0; Target
< DeviceExtension
->PortConfig
->MaximumNumberOfTargets
; Target
++)
2532 for (Lun
= 0; Lun
< SCSI_MAXIMUM_LOGICAL_UNITS
; Lun
++)
2534 LunExtension
= SpiGetLunExtension(DeviceExtension
,
2538 if (LunExtension
!= NULL
)
2540 if (Target
!= CurrentTarget
)
2542 /* Close old target key */
2543 if (ScsiTargetKey
!= NULL
)
2545 ZwClose(ScsiTargetKey
);
2546 ScsiTargetKey
= NULL
;
2549 /* Create 'Target Id X' key */
2550 DPRINT(" Target Id %lu\n", Target
);
2551 swprintf(NameBuffer
,
2554 RtlInitUnicodeString(&KeyName
,
2556 InitializeObjectAttributes(&ObjectAttributes
,
2561 Status
= ZwCreateKey(&ScsiTargetKey
,
2566 REG_OPTION_VOLATILE
,
2568 if (!NT_SUCCESS(Status
))
2570 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status
);
2574 CurrentTarget
= Target
;
2577 /* Create 'Logical Unit Id X' key */
2578 DPRINT(" Logical Unit Id %lu\n", Lun
);
2579 swprintf(NameBuffer
,
2580 L
"Logical Unit Id %lu",
2582 RtlInitUnicodeString(&KeyName
,
2584 InitializeObjectAttributes(&ObjectAttributes
,
2589 Status
= ZwCreateKey(&ScsiLunKey
,
2594 REG_OPTION_VOLATILE
,
2596 if (!NT_SUCCESS(Status
))
2598 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status
);
2602 /* Set 'Identifier' (REG_SZ) value */
2603 swprintf(NameBuffer
,
2605 LunExtension
->InquiryData
.VendorId
,
2606 LunExtension
->InquiryData
.ProductId
,
2607 LunExtension
->InquiryData
.ProductRevisionLevel
);
2608 DPRINT(" Identifier = '%S'\n", NameBuffer
);
2609 RtlInitUnicodeString(&ValueName
,
2611 Status
= ZwSetValueKey(ScsiLunKey
,
2616 (wcslen(NameBuffer
) + 1) * sizeof(WCHAR
));
2617 if (!NT_SUCCESS(Status
))
2619 DPRINT("ZwSetValueKey('Identifier') failed (Status %lx)\n", Status
);
2623 /* Set 'Type' (REG_SZ) value */
2624 switch (LunExtension
->InquiryData
.DeviceType
)
2627 TypeName
= L
"DiskPeripheral";
2630 TypeName
= L
"TapePeripheral";
2633 TypeName
= L
"PrinterPeripheral";
2636 TypeName
= L
"WormPeripheral";
2639 TypeName
= L
"CdRomPeripheral";
2642 TypeName
= L
"ScannerPeripheral";
2645 TypeName
= L
"OpticalDiskPeripheral";
2648 TypeName
= L
"MediumChangerPeripheral";
2651 TypeName
= L
"CommunicationPeripheral";
2654 TypeName
= L
"OtherPeripheral";
2657 DPRINT(" Type = '%S'\n", TypeName
);
2658 RtlInitUnicodeString(&ValueName
,
2660 Status
= ZwSetValueKey(ScsiLunKey
,
2665 (wcslen(TypeName
) + 1) * sizeof(WCHAR
));
2666 if (!NT_SUCCESS(Status
))
2668 DPRINT("ZwSetValueKey('Type') failed (Status %lx)\n", Status
);
2672 ZwClose(ScsiLunKey
);
2677 /* Close old target key */
2678 if (ScsiTargetKey
!= NULL
)
2680 ZwClose(ScsiTargetKey
);
2681 ScsiTargetKey
= NULL
;
2685 ZwClose(ScsiBusKey
);
2690 if (ScsiLunKey
!= NULL
)
2691 ZwClose (ScsiLunKey
);
2693 if (ScsiInitiatorKey
!= NULL
)
2694 ZwClose (ScsiInitiatorKey
);
2696 if (ScsiTargetKey
!= NULL
)
2697 ZwClose (ScsiTargetKey
);
2699 if (ScsiBusKey
!= NULL
)
2700 ZwClose (ScsiBusKey
);
2702 if (ScsiPortKey
!= NULL
)
2703 ZwClose (ScsiPortKey
);
2705 DPRINT("SpiBuildDeviceMap() done\n");
2711 SpiRemoveActiveIrp(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
2715 PSCSI_PORT_LUN_EXTENSION LunExtension
;
2717 LunExtension
= Irp
->Tail
.Overlay
.DriverContext
[2];
2718 LunExtension
->ActiveIrpCount
--;
2719 DeviceExtension
->ActiveIrpCount
--;
2722 InterlockedExchangePointer(&PrevIrp
->Tail
.Overlay
.DriverContext
[0],
2723 Irp
->Tail
.Overlay
.DriverContext
[0]);
2727 InterlockedExchangePointer(&DeviceExtension
->NextIrp
,
2728 Irp
->Tail
.Overlay
.DriverContext
[0]);
2730 if (LunExtension
->NextIrp
== Irp
)
2732 InterlockedExchangePointer(&LunExtension
->NextIrp
,
2733 Irp
->Tail
.Overlay
.DriverContext
[1]);
2738 CurrentIrp
= LunExtension
->NextIrp
;
2741 if (CurrentIrp
->Tail
.Overlay
.DriverContext
[1] == Irp
)
2743 InterlockedExchangePointer(&CurrentIrp
->Tail
.Overlay
.DriverContext
[1],
2744 Irp
->Tail
.Overlay
.DriverContext
[1]);
2747 CurrentIrp
= CurrentIrp
->Tail
.Overlay
.DriverContext
[1];
2754 SpiAddActiveIrp(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
2757 PSCSI_PORT_LUN_EXTENSION LunExtension
;
2758 LunExtension
= Irp
->Tail
.Overlay
.DriverContext
[2];
2759 Irp
->Tail
.Overlay
.DriverContext
[0] = (PVOID
)DeviceExtension
->NextIrp
;
2760 InterlockedExchangePointer(&DeviceExtension
->NextIrp
, Irp
);
2761 Irp
->Tail
.Overlay
.DriverContext
[1] = (PVOID
)LunExtension
->NextIrp
;
2762 InterlockedExchangePointer(&LunExtension
->NextIrp
, Irp
);
2766 SpiProcessRequests(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
2770 * Using of some fields from Srb and Irp while processing requests:
2773 * Srb->OriginalRequest -> LunExtension
2774 * Irp->Tail.Overlay.DriverContext[3] -> original Srb
2775 * IoStack->Parameters.Scsi.Srb -> original Srb
2777 * Irp is within the pending irp list:
2778 * Srb->OriginalRequest -> LunExtension
2779 * Irp->Tail.Overlay.DriverContext[0] and DriverContext[1] -> ListEntry for queue
2780 * Irp->Tail.Overlay.DriverContext[2] -> sort key (from Srb->QueueSortKey)
2781 * Irp->Tail.Overlay.DriverContext[3] -> current Srb (original or sense request)
2782 * IoStack->Parameters.Scsi.Srb -> original Srb
2784 * Irp is within the active irp list or while other processing:
2785 * Srb->OriginalRequest -> Irp
2786 * Irp->Tail.Overlay.DriverContext[0] -> next irp, DeviceExtension->NextIrp is head.
2787 * Irp->Tail.Overlay.DriverContext[1] -> next irp, LunExtension->NextIrp is head.
2788 * Irp->Tail.Overlay.DriverContext[2] -> LunExtension
2789 * Irp->Tail.Overlay.DriverContext[3] -> current Srb (original or sense request)
2790 * IoStack->Parameters.Scsi.Srb -> original Srb
2792 PIO_STACK_LOCATION IrpStack
;
2793 PSCSI_PORT_LUN_EXTENSION LunExtension
;
2794 PLIST_ENTRY ListEntry
;
2797 LIST_ENTRY NextIrpListHead
;
2798 LIST_ENTRY CompleteIrpListHead
;
2799 PSCSI_REQUEST_BLOCK Srb
;
2800 PSCSI_REQUEST_BLOCK OriginalSrb
;
2803 DPRINT("SpiProcessRequests() called\n");
2805 InitializeListHead(&NextIrpListHead
);
2806 InitializeListHead(&CompleteIrpListHead
);
2808 KeAcquireSpinLock(&DeviceExtension
->Lock
, &oldIrql
);
2812 Srb
= NextIrp
->Tail
.Overlay
.DriverContext
[3];
2813 NextIrp
->Tail
.Overlay
.DriverContext
[2] = (PVOID
)Srb
->QueueSortKey
;
2814 LunExtension
= Srb
->OriginalRequest
;
2816 ListEntry
= DeviceExtension
->PendingIrpListHead
.Flink
;
2817 while (ListEntry
!= DeviceExtension
->PendingIrpListHead
.Flink
)
2819 Irp
= CONTAINING_RECORD(ListEntry
, IRP
, Tail
.Overlay
.DriverContext
[0]);
2820 if ((ULONG
)Irp
->Tail
.Overlay
.DriverContext
[2] > Srb
->QueueSortKey
)
2824 ListEntry
= ListEntry
->Flink
;
2826 InsertTailList(ListEntry
, (PLIST_ENTRY
)&NextIrp
->Tail
.Overlay
.DriverContext
[0]);
2827 DeviceExtension
->PendingIrpCount
++;
2828 LunExtension
->PendingIrpCount
++;
2831 while (DeviceExtension
->CompleteRequestCount
||
2832 ((DeviceExtension
->SrbExtensionSize
== 0 || DeviceExtension
->ActiveIrpCount
< MAX_SRB_EXTENSIONS
) && !IsListEmpty(&DeviceExtension
->PendingIrpListHead
) &&
2833 (DeviceExtension
->NextRequestCount
|| DeviceExtension
->NextLuRequestCount
|| DeviceExtension
->NextIrp
== NULL
)))
2835 DPRINT ("CompleteRequestCount %d, NextRequestCount %d, NextLuRequestCount %d, PendingIrpList is %s, ActiveIrpList is %s\n",
2836 DeviceExtension
->CompleteRequestCount
,
2837 DeviceExtension
->NextRequestCount
,
2838 DeviceExtension
->NextLuRequestCount
,
2839 IsListEmpty(&DeviceExtension
->PendingIrpListHead
) ? "EMPTY" : "NOT empty",
2840 DeviceExtension
->NextIrp
== NULL
? "EMPTY" : "NOT empty");
2842 if (DeviceExtension
->ActiveIrpCount
== 0 && DeviceExtension
->CompleteRequestCount
> 0)
2844 DeviceExtension
->CompleteRequestCount
= 0;
2848 if (DeviceExtension
->CompleteRequestCount
> 0)
2850 DeviceExtension
->Flags
&= ~IRP_FLAG_COMPLETE
;
2852 Irp
= DeviceExtension
->NextIrp
;
2855 NextIrp
= (PIRP
)Irp
->Tail
.Overlay
.DriverContext
[0];
2856 Srb
= Irp
->Tail
.Overlay
.DriverContext
[3];
2857 if (!(Srb
->SrbFlags
& SRB_FLAGS_IS_ACTIVE
))
2859 BOOLEAN CompleteThisRequest
;
2860 InterlockedDecrement((PLONG
)&DeviceExtension
->CompleteRequestCount
);
2861 LunExtension
= Irp
->Tail
.Overlay
.DriverContext
[2];
2862 IrpStack
= IoGetCurrentIrpStackLocation(Irp
);
2863 OriginalSrb
= IrpStack
->Parameters
.Scsi
.Srb
;
2865 if (Srb
->SrbStatus
== SRB_STATUS_BUSY
)
2867 SpiRemoveActiveIrp(DeviceExtension
, Irp
, PrevIrp
);
2868 SpiFreeSrbExtension(DeviceExtension
, OriginalSrb
);
2869 InsertHeadList(&DeviceExtension
->PendingIrpListHead
, (PLIST_ENTRY
)&Irp
->Tail
.Overlay
.DriverContext
[0]);
2870 DeviceExtension
->PendingIrpCount
++;
2871 LunExtension
->PendingIrpCount
++;
2876 if (OriginalSrb
!= Srb
)
2878 SENSE_DATA
* SenseInfoBuffer
;
2880 SenseInfoBuffer
= Srb
->DataBuffer
;
2882 DPRINT("Got sense data!\n");
2884 DPRINT("Valid: %x\n", SenseInfoBuffer
->Valid
);
2885 DPRINT("ErrorCode: %x\n", SenseInfoBuffer
->ErrorCode
);
2886 DPRINT("SenseKey: %x\n", SenseInfoBuffer
->SenseKey
);
2887 DPRINT("SenseCode: %x\n", SenseInfoBuffer
->AdditionalSenseCode
);
2889 /* Copy sense data */
2890 RtlCopyMemory(OriginalSrb
->SenseInfoBuffer
,
2892 sizeof(SENSE_DATA
));
2893 OriginalSrb
->SrbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2895 CompleteThisRequest
= TRUE
;
2897 else if (SRB_STATUS(Srb
->SrbStatus
) != SRB_STATUS_SUCCESS
&&
2898 Srb
->ScsiStatus
== SCSISTAT_CHECK_CONDITION
&&
2899 Srb
->SenseInfoBuffer
!= NULL
&&
2900 Srb
->SenseInfoBufferLength
>= sizeof(SENSE_DATA
) &&
2901 !(Srb
->SrbStatus
& SRB_STATUS_AUTOSENSE_VALID
))
2903 DPRINT("SCSIOP_REQUEST_SENSE required!\n");
2905 Srb
= ScsiPortInitSenseRequestSrb(OriginalSrb
);
2909 CompleteThisRequest
= FALSE
;
2910 Irp
->Tail
.Overlay
.DriverContext
[3] = Srb
;
2911 SpiRemoveActiveIrp(DeviceExtension
, Irp
, PrevIrp
);
2912 SpiFreeSrbExtension(DeviceExtension
, Srb
);
2914 Srb
->OriginalRequest
= LunExtension
;
2915 Irp
->Tail
.Overlay
.DriverContext
[2] = 0;
2917 InsertHeadList(&DeviceExtension
->PendingIrpListHead
, (PLIST_ENTRY
)&Irp
->Tail
.Overlay
.DriverContext
[0]);
2918 DeviceExtension
->PendingIrpCount
++;
2919 LunExtension
->PendingIrpCount
++;
2925 CompleteThisRequest
= TRUE
;
2930 DPRINT("Complete Request\n");
2931 CompleteThisRequest
= TRUE
;
2933 if (CompleteThisRequest
)
2935 SpiRemoveActiveIrp(DeviceExtension
, Irp
, PrevIrp
);
2936 InsertHeadList(&CompleteIrpListHead
, (PLIST_ENTRY
)&Irp
->Tail
.Overlay
.DriverContext
[0]);
2937 SpiFreeSrbExtension(DeviceExtension
, OriginalSrb
);
2950 if (!IsListEmpty(&CompleteIrpListHead
))
2952 KeReleaseSpinLockFromDpcLevel(&DeviceExtension
->Lock
);
2953 while (!IsListEmpty(&CompleteIrpListHead
))
2955 ListEntry
= RemoveTailList(&CompleteIrpListHead
);
2956 Irp
= CONTAINING_RECORD(ListEntry
, IRP
, Tail
.Overlay
.DriverContext
[0]);
2957 Srb
= Irp
->Tail
.Overlay
.DriverContext
[3];
2958 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2960 KeAcquireSpinLockAtDpcLevel(&DeviceExtension
->Lock
);
2962 if (DeviceExtension
->NextLuRequestCount
||
2963 DeviceExtension
->NextRequestCount
)
2965 BOOLEAN StartThisRequest
;
2966 DeviceExtension
->Flags
&= ~(IRP_FLAG_NEXT
|IRP_FLAG_NEXT_LU
);
2967 ListEntry
= DeviceExtension
->PendingIrpListHead
.Flink
;
2968 while (ListEntry
!= &DeviceExtension
->PendingIrpListHead
)
2970 Irp
= CONTAINING_RECORD(ListEntry
, IRP
, Tail
.Overlay
.DriverContext
[0]);
2971 ListEntry
= ListEntry
->Flink
;
2972 Srb
= Irp
->Tail
.Overlay
.DriverContext
[3];
2973 LunExtension
= Srb
->OriginalRequest
;
2974 if (DeviceExtension
->SrbExtensionSize
> 0 &&
2975 DeviceExtension
->ActiveIrpCount
>= MAX_SRB_EXTENSIONS
)
2979 if (LunExtension
->NextLuRequestCount
> 0)
2981 StartThisRequest
= TRUE
;
2982 InterlockedDecrement((PLONG
)&LunExtension
->NextLuRequestCount
);
2983 InterlockedDecrement((PLONG
)&DeviceExtension
->NextLuRequestCount
);
2985 else if (DeviceExtension
->NextRequestCount
> 0 &&
2986 LunExtension
->ActiveIrpCount
== 0)
2988 InterlockedDecrement((PLONG
)&DeviceExtension
->NextRequestCount
);
2989 StartThisRequest
= TRUE
;
2993 StartThisRequest
= FALSE
;
2995 if (StartThisRequest
)
2997 LunExtension
->PendingIrpCount
--;
2998 DeviceExtension
->PendingIrpCount
--;
2999 RemoveEntryList((PLIST_ENTRY
)&Irp
->Tail
.Overlay
.DriverContext
[0]);
3000 LunExtension
->ActiveIrpCount
++;
3001 DeviceExtension
->ActiveIrpCount
++;
3002 SpiAllocateSrbExtension(DeviceExtension
, Srb
);
3004 Irp
->Tail
.Overlay
.DriverContext
[2] = LunExtension
;
3005 Srb
->OriginalRequest
= Irp
;
3007 InsertHeadList(&NextIrpListHead
, (PLIST_ENTRY
)&Irp
->Tail
.Overlay
.DriverContext
[0]);
3012 if (!IsListEmpty(&NextIrpListHead
))
3014 while (!IsListEmpty(&NextIrpListHead
))
3016 ListEntry
= RemoveTailList(&NextIrpListHead
);
3017 Irp
= CONTAINING_RECORD(ListEntry
, IRP
, Tail
.Overlay
.DriverContext
[0]);
3018 SpiAddActiveIrp(DeviceExtension
, Irp
);
3019 KeReleaseSpinLockFromDpcLevel(&DeviceExtension
->Lock
);
3022 SpiStartIo(DeviceExtension
, Irp
);
3023 KeAcquireSpinLockAtDpcLevel(&DeviceExtension
->Lock
);
3027 if (!IsListEmpty(&DeviceExtension
->PendingIrpListHead
) &&
3028 DeviceExtension
->NextIrp
== NULL
&&
3029 (DeviceExtension
->SrbExtensionSize
== 0 || DeviceExtension
->ActiveIrpCount
< MAX_SRB_EXTENSIONS
))
3031 ListEntry
= RemoveHeadList(&DeviceExtension
->PendingIrpListHead
);
3032 Irp
= CONTAINING_RECORD(ListEntry
, IRP
, Tail
.Overlay
.DriverContext
[0]);
3033 Srb
= Irp
->Tail
.Overlay
.DriverContext
[3];
3034 LunExtension
= Srb
->OriginalRequest
;
3035 Irp
->Tail
.Overlay
.DriverContext
[2] = LunExtension
;
3036 Srb
->OriginalRequest
= Irp
;
3038 LunExtension
->PendingIrpCount
--;
3039 DeviceExtension
->PendingIrpCount
--;
3040 SpiAddActiveIrp(DeviceExtension
, Irp
);
3041 LunExtension
->ActiveIrpCount
++;
3042 DeviceExtension
->ActiveIrpCount
++;
3043 SpiAllocateSrbExtension(DeviceExtension
, Srb
);
3044 KeReleaseSpinLockFromDpcLevel(&DeviceExtension
->Lock
);
3046 /* Start this irp */
3047 SpiStartIo(DeviceExtension
, Irp
);
3048 KeAcquireSpinLockAtDpcLevel(&DeviceExtension
->Lock
);
3051 KeReleaseSpinLock(&DeviceExtension
->Lock
, oldIrql
);
3053 DPRINT("SpiProcessRequests() done\n");
3057 SpiStartIo(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
3060 PSCSI_PORT_LUN_EXTENSION LunExtension
;
3061 PSCSI_REQUEST_BLOCK Srb
;
3063 DPRINT("SpiStartIo() called!\n");
3065 assert(KeGetCurrentIrql() == DISPATCH_LEVEL
);
3067 Srb
= Irp
->Tail
.Overlay
.DriverContext
[3];
3068 LunExtension
= Irp
->Tail
.Overlay
.DriverContext
[2];
3070 Srb
->SrbFlags
|= SRB_FLAGS_IS_ACTIVE
;
3071 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
3072 Irp
->IoStatus
.Information
= Srb
->DataTransferLength
;
3074 if (!KeSynchronizeExecution(DeviceExtension
->Interrupt
,
3075 ScsiPortStartPacket
,
3078 DPRINT1("Synchronization failed!\n");
3079 DPRINT1("Irp %x, Srb->Function %02x, Srb->Cdb[0] %02x, Srb->SrbStatus %02x\n", Irp
, Srb
->Function
, Srb
->Cdb
[0], Srb
->SrbStatus
);
3080 ScsiPortNotification(RequestComplete
,
3081 &DeviceExtension
->MiniPortDeviceExtension
,
3085 DPRINT("SpiStartIo() done\n");