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.31 2003/08/27 21:30:37 dwelch 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)
28 /* INCLUDES *****************************************************************/
30 #include <ddk/ntddk.h>
33 #include <ddk/ntddscsi.h>
39 #define VERSION "0.0.1"
41 #include "scsiport_int.h"
43 /* TYPES *********************************************************************/
45 #define IRP_FLAG_COMPLETE 0x00000001
46 #define IRP_FLAG_NEXT 0x00000002
49 /* GLOBALS *******************************************************************/
51 static NTSTATUS STDCALL
52 ScsiPortCreateClose(IN PDEVICE_OBJECT DeviceObject
,
55 static NTSTATUS STDCALL
56 ScsiPortDispatchScsi(IN PDEVICE_OBJECT DeviceObject
,
59 static NTSTATUS STDCALL
60 ScsiPortDeviceControl(IN PDEVICE_OBJECT DeviceObject
,
64 ScsiPortStartIo(IN PDEVICE_OBJECT DeviceObject
,
67 static IO_ALLOCATION_ACTION STDCALL
68 ScsiPortAllocateController(IN PDEVICE_OBJECT DeviceObject
,
70 IN PVOID MapRegisterBase
,
73 static BOOLEAN STDCALL
74 ScsiPortStartPacket(IN OUT PVOID Context
);
77 ScsiPortCreatePortDevice(IN PDRIVER_OBJECT DriverObject
,
78 IN PSCSI_PORT_DEVICE_EXTENSION PseudoDeviceExtension
,
80 IN OUT PSCSI_PORT_DEVICE_EXTENSION
*RealDeviceExtension
);
83 ScsiPortInquire(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
);
85 static BOOLEAN STDCALL
86 ScsiPortIsr(IN PKINTERRUPT Interrupt
,
87 IN PVOID ServiceContext
);
90 ScsiPortDpcForIsr(IN PKDPC Dpc
,
91 IN PDEVICE_OBJECT DpcDeviceObject
,
96 ScsiPortIoTimer(PDEVICE_OBJECT DeviceObject
,
99 static PSCSI_REQUEST_BLOCK
100 ScsiPortInitSenseRequestSrb(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
101 PSCSI_REQUEST_BLOCK OriginalSrb
);
104 ScsiPortBuildDeviceMap(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
105 PUNICODE_STRING RegistryPath
);
108 /* FUNCTIONS *****************************************************************/
110 /**********************************************************************
115 * This function initializes the driver.
122 * System allocated Driver Object for this driver.
125 * Name of registry driver service key.
132 DriverEntry(IN PDRIVER_OBJECT DriverObject
,
133 IN PUNICODE_STRING RegistryPath
)
135 DPRINT("ScsiPort Driver %s\n", VERSION
);
136 return(STATUS_SUCCESS
);
140 /**********************************************************************
145 * Prints debugging messages.
152 * Debug level of the given message.
155 * Pointer to printf()-compatible format string.
158 Additional output data (see printf()).
167 ScsiDebugPrint(IN ULONG DebugPrintLevel
,
168 IN PCHAR DebugMessage
,
175 if (DebugPrintLevel
> InternalDebugLevel
)
179 va_start(ap
, DebugMessage
);
180 vsprintf(Buffer
, DebugMessage
, ap
);
191 ScsiPortCompleteRequest(IN PVOID HwDeviceExtension
,
197 DPRINT("ScsiPortCompleteRequest()\n");
206 ScsiPortConvertPhysicalAddressToUlong(IN SCSI_PHYSICAL_ADDRESS Address
)
208 DPRINT("ScsiPortConvertPhysicalAddressToUlong()\n");
209 return(Address
.u
.LowPart
);
217 ScsiPortFlushDma(IN PVOID HwDeviceExtension
)
219 DPRINT("ScsiPortFlushDma()\n");
228 ScsiPortFreeDeviceBase(IN PVOID HwDeviceExtension
,
229 IN PVOID MappedAddress
)
231 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
232 PSCSI_PORT_DEVICE_BASE DeviceBase
;
235 DPRINT("ScsiPortFreeDeviceBase() called\n");
237 DeviceExtension
= CONTAINING_RECORD(HwDeviceExtension
,
238 SCSI_PORT_DEVICE_EXTENSION
,
239 MiniPortDeviceExtension
);
240 if (IsListEmpty(&DeviceExtension
->DeviceBaseListHead
))
243 Entry
= DeviceExtension
->DeviceBaseListHead
.Flink
;
244 while (Entry
!= &DeviceExtension
->DeviceBaseListHead
)
246 DeviceBase
= CONTAINING_RECORD(Entry
,
247 SCSI_PORT_DEVICE_BASE
,
249 if (DeviceBase
->MappedAddress
== MappedAddress
)
251 MmUnmapIoSpace(DeviceBase
->MappedAddress
,
252 DeviceBase
->NumberOfBytes
);
253 RemoveEntryList(Entry
);
254 ExFreePool(DeviceBase
);
259 Entry
= Entry
->Flink
;
268 ScsiPortGetBusData(IN PVOID DeviceExtension
,
269 IN ULONG BusDataType
,
270 IN ULONG SystemIoBusNumber
,
275 return(HalGetBusData(BusDataType
,
287 ScsiPortGetDeviceBase(IN PVOID HwDeviceExtension
,
288 IN INTERFACE_TYPE BusType
,
289 IN ULONG SystemIoBusNumber
,
290 IN SCSI_PHYSICAL_ADDRESS IoAddress
,
291 IN ULONG NumberOfBytes
,
292 IN BOOLEAN InIoSpace
)
294 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
295 PHYSICAL_ADDRESS TranslatedAddress
;
296 PSCSI_PORT_DEVICE_BASE DeviceBase
;
300 DPRINT("ScsiPortGetDeviceBase() called\n");
302 AddressSpace
= (ULONG
)InIoSpace
;
303 if (HalTranslateBusAddress(BusType
,
307 &TranslatedAddress
) == FALSE
)
311 if (AddressSpace
!= 0)
312 return((PVOID
)TranslatedAddress
.u
.LowPart
);
314 MappedAddress
= MmMapIoSpace(TranslatedAddress
,
318 DeviceBase
= ExAllocatePool(NonPagedPool
,
319 sizeof(SCSI_PORT_DEVICE_BASE
));
320 if (DeviceBase
== NULL
)
321 return(MappedAddress
);
323 DeviceBase
->MappedAddress
= MappedAddress
;
324 DeviceBase
->NumberOfBytes
= NumberOfBytes
;
325 DeviceBase
->IoAddress
= IoAddress
;
326 DeviceBase
->SystemIoBusNumber
= SystemIoBusNumber
;
328 DeviceExtension
= CONTAINING_RECORD(HwDeviceExtension
,
329 SCSI_PORT_DEVICE_EXTENSION
,
330 MiniPortDeviceExtension
);
332 InsertHeadList(&DeviceExtension
->DeviceBaseListHead
,
335 return(MappedAddress
);
343 ScsiPortGetLogicalUnit(IN PVOID HwDeviceExtension
,
348 DPRINT("ScsiPortGetLogicalUnit()\n");
356 SCSI_PHYSICAL_ADDRESS STDCALL
357 ScsiPortGetPhysicalAddress(IN PVOID HwDeviceExtension
,
358 IN PSCSI_REQUEST_BLOCK Srb OPTIONAL
,
359 IN PVOID VirtualAddress
,
362 DPRINT("ScsiPortGetPhysicalAddress()\n");
370 PSCSI_REQUEST_BLOCK STDCALL
371 ScsiPortGetSrb(IN PVOID DeviceExtension
,
377 DPRINT("ScsiPortGetSrb()\n");
386 ScsiPortGetUncachedExtension(IN PVOID HwDeviceExtension
,
387 IN PPORT_CONFIGURATION_INFORMATION ConfigInfo
,
388 IN ULONG NumberOfBytes
)
390 DPRINT("ScsiPortGetUncachedExtension()\n");
399 ScsiPortGetVirtualAddress(IN PVOID HwDeviceExtension
,
400 IN SCSI_PHYSICAL_ADDRESS PhysicalAddress
)
402 DPRINT("ScsiPortGetVirtualAddress()\n");
407 /**********************************************************************
412 * Initializes SCSI port driver specific data.
419 * Pointer to the miniport driver's driver object.
422 * Pointer to the miniport driver's registry path.
424 * HwInitializationData
425 * Pointer to port driver specific configuration data.
428 Miniport driver specific context.
437 ScsiPortInitialize(IN PVOID Argument1
,
439 IN
struct _HW_INITIALIZATION_DATA
*HwInitializationData
,
442 PDRIVER_OBJECT DriverObject
= (PDRIVER_OBJECT
)Argument1
;
443 PUNICODE_STRING RegistryPath
= (PUNICODE_STRING
)Argument2
;
444 PSCSI_PORT_DEVICE_EXTENSION PseudoDeviceExtension
;
445 PSCSI_PORT_DEVICE_EXTENSION RealDeviceExtension
;
446 PCONFIGURATION_INFORMATION SystemConfig
;
447 PPORT_CONFIGURATION_INFORMATION PortConfig
;
453 PACCESS_RANGE AccessRanges
;
456 DPRINT("ScsiPortInitialize() called!\n");
458 if ((HwInitializationData
->HwInitialize
== NULL
) ||
459 (HwInitializationData
->HwStartIo
== NULL
) ||
460 (HwInitializationData
->HwInterrupt
== NULL
) ||
461 (HwInitializationData
->HwFindAdapter
== NULL
) ||
462 (HwInitializationData
->HwResetBus
== NULL
))
463 return(STATUS_INVALID_PARAMETER
);
465 DriverObject
->DriverStartIo
= ScsiPortStartIo
;
466 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = ScsiPortCreateClose
;
467 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = ScsiPortCreateClose
;
468 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = ScsiPortDeviceControl
;
469 DriverObject
->MajorFunction
[IRP_MJ_SCSI
] = ScsiPortDispatchScsi
;
472 SystemConfig
= IoGetConfigurationInformation();
474 ExtensionSize
= sizeof(SCSI_PORT_DEVICE_EXTENSION
) +
475 HwInitializationData
->DeviceExtensionSize
;
476 PseudoDeviceExtension
= ExAllocatePool(PagedPool
,
478 RtlZeroMemory(PseudoDeviceExtension
,
480 PseudoDeviceExtension
->Length
= ExtensionSize
;
481 PseudoDeviceExtension
->MiniPortExtensionSize
= HwInitializationData
->DeviceExtensionSize
;
482 PseudoDeviceExtension
->HwStartIo
= HwInitializationData
->HwStartIo
;
483 PseudoDeviceExtension
->HwInterrupt
= HwInitializationData
->HwInterrupt
;
485 PortConfig
= &PseudoDeviceExtension
->PortConfig
;
487 PortConfig
->Length
= sizeof(PORT_CONFIGURATION_INFORMATION
);
488 PortConfig
->AdapterInterfaceType
= HwInitializationData
->AdapterInterfaceType
;
489 PortConfig
->InterruptMode
=
490 (PortConfig
->AdapterInterfaceType
== PCIBus
) ? LevelSensitive
: Latched
;
491 PortConfig
->AtdiskPrimaryClaimed
= SystemConfig
->AtDiskPrimaryAddressClaimed
;
492 PortConfig
->AtdiskSecondaryClaimed
= SystemConfig
->AtDiskSecondaryAddressClaimed
;
493 PortConfig
->NumberOfAccessRanges
= HwInitializationData
->NumberOfAccessRanges
;
495 PortConfig
->AccessRanges
=
496 ExAllocatePool(PagedPool
,
497 sizeof(ACCESS_RANGE
) * PortConfig
->NumberOfAccessRanges
);
499 for (i
= 0; i
< SCSI_MAXIMUM_BUSES
; i
++)
500 PortConfig
->InitiatorBusId
[i
] = 255;
502 PortConfig
->SystemIoBusNumber
= 0;
503 PortConfig
->SlotNumber
= 0;
505 MaxBus
= (PortConfig
->AdapterInterfaceType
== PCIBus
) ? 8 : 1;
507 DPRINT("MaxBus: %lu\n", MaxBus
);
511 DPRINT("Calling HwFindAdapter() for Bus %lu\n", PortConfig
->SystemIoBusNumber
);
513 InitializeListHead(&PseudoDeviceExtension
->DeviceBaseListHead
);
515 // RtlZeroMemory(AccessRanges,
516 // sizeof(ACCESS_RANGE) * PortConfig->NumberOfAccessRanges);
518 RtlZeroMemory(PseudoDeviceExtension
->MiniPortDeviceExtension
,
519 PseudoDeviceExtension
->MiniPortExtensionSize
);
521 /* Note: HwFindAdapter is called once for each bus */
522 Result
= (HwInitializationData
->HwFindAdapter
)(&PseudoDeviceExtension
->MiniPortDeviceExtension
,
524 NULL
, /* BusInformation */
525 NULL
, /* ArgumentString */
526 &PseudoDeviceExtension
->PortConfig
,
528 DPRINT("HwFindAdapter() result: %lu\n", Result
);
530 if (Result
== SP_RETURN_FOUND
)
532 DPRINT("ScsiPortInitialize(): Found HBA!\n");
534 Status
= ScsiPortCreatePortDevice(DriverObject
,
535 PseudoDeviceExtension
,
536 SystemConfig
->ScsiPortCount
,
537 &RealDeviceExtension
);
539 if (!NT_SUCCESS(Status
))
541 DbgPrint("ScsiPortCreatePortDevice() failed! (Status 0x%lX)\n", Status
);
543 ExFreePool(PortConfig
->AccessRanges
);
544 ExFreePool(PseudoDeviceExtension
);
549 /* Build the registry device map */
550 ScsiPortBuildDeviceMap(RealDeviceExtension
,
551 (PUNICODE_STRING
)Argument2
);
553 /* Update the configuration info */
554 SystemConfig
->AtDiskPrimaryAddressClaimed
= PortConfig
->AtdiskPrimaryClaimed
;
555 SystemConfig
->AtDiskSecondaryAddressClaimed
= PortConfig
->AtdiskSecondaryClaimed
;
556 SystemConfig
->ScsiPortCount
++;
561 PortConfig
->SystemIoBusNumber
++;
562 PortConfig
->SlotNumber
= 0;
565 DPRINT("Bus: %lu MaxBus: %lu\n", PortConfig
->SystemIoBusNumber
, MaxBus
);
566 if (PortConfig
->SystemIoBusNumber
>= MaxBus
)
568 DPRINT("Scanned all buses!\n");
573 ExFreePool(PortConfig
->AccessRanges
);
574 ExFreePool(PseudoDeviceExtension
);
576 DPRINT("ScsiPortInitialize() done!\n");
578 return(STATUS_SUCCESS
);
586 ScsiPortIoMapTransfer(IN PVOID HwDeviceExtension
,
587 IN PSCSI_REQUEST_BLOCK Srb
,
588 IN ULONG LogicalAddress
,
591 DPRINT("ScsiPortIoMapTransfer()\n");
600 ScsiPortLogError(IN PVOID HwDeviceExtension
,
601 IN PSCSI_REQUEST_BLOCK Srb OPTIONAL
,
608 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
610 DPRINT("ScsiPortLogError() called\n");
612 DeviceExtension
= CONTAINING_RECORD(HwDeviceExtension
,
613 SCSI_PORT_DEVICE_EXTENSION
,
614 MiniPortDeviceExtension
);
617 DPRINT("ScsiPortLogError() done\n");
625 ScsiPortMoveMemory(OUT PVOID Destination
,
629 RtlMoveMemory(Destination
,
639 ScsiPortNotification(IN SCSI_NOTIFICATION_TYPE NotificationType
,
640 IN PVOID HwDeviceExtension
,
643 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
645 DPRINT("ScsiPortNotification() called\n");
647 DeviceExtension
= CONTAINING_RECORD(HwDeviceExtension
,
648 SCSI_PORT_DEVICE_EXTENSION
,
649 MiniPortDeviceExtension
);
651 DPRINT("DeviceExtension %p\n", DeviceExtension
);
653 DPRINT("Initializing = %s\n", (DeviceExtension
->Initializing
)?"TRUE":"FALSE");
655 if (DeviceExtension
->Initializing
== TRUE
)
658 switch (NotificationType
)
660 case RequestComplete
:
661 DPRINT("Notify: RequestComplete\n");
662 DeviceExtension
->IrpFlags
|= IRP_FLAG_COMPLETE
;
666 DPRINT("Notify: NextRequest\n");
667 DeviceExtension
->IrpFlags
|= IRP_FLAG_NEXT
;
680 ScsiPortSetBusDataByOffset(IN PVOID DeviceExtension
,
681 IN ULONG BusDataType
,
682 IN ULONG SystemIoBusNumber
,
688 DPRINT("ScsiPortSetBusDataByOffset()\n");
689 return(HalSetBusDataByOffset(BusDataType
,
702 ScsiPortValidateRange(IN PVOID HwDeviceExtension
,
703 IN INTERFACE_TYPE BusType
,
704 IN ULONG SystemIoBusNumber
,
705 IN SCSI_PHYSICAL_ADDRESS IoAddress
,
706 IN ULONG NumberOfBytes
,
707 IN BOOLEAN InIoSpace
)
709 DPRINT("ScsiPortValidateRange()\n");
714 /* INTERNAL FUNCTIONS ********************************************************/
716 /**********************************************************************
718 * ScsiPortCreateClose
721 * Answer requests for Create/Close calls: a null operation.
728 * Pointer to a device object.
734 Additional output data (see printf()).
740 static NTSTATUS STDCALL
741 ScsiPortCreateClose(IN PDEVICE_OBJECT DeviceObject
,
744 DPRINT("ScsiPortCreateClose()\n");
746 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
747 Irp
->IoStatus
.Information
= FILE_OPENED
;
749 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
751 return(STATUS_SUCCESS
);
755 /**********************************************************************
757 * ScsiPortDispatchScsi
760 * Answer requests for SCSI calls
766 * Standard dispatch arguments
772 static NTSTATUS STDCALL
773 ScsiPortDispatchScsi(IN PDEVICE_OBJECT DeviceObject
,
776 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
777 PIO_STACK_LOCATION Stack
;
778 PSCSI_REQUEST_BLOCK Srb
;
779 NTSTATUS Status
= STATUS_SUCCESS
;
782 DPRINT("ScsiPortDispatchScsi(DeviceObject %p Irp %p)\n",
785 DeviceExtension
= DeviceObject
->DeviceExtension
;
786 Stack
= IoGetCurrentIrpStackLocation(Irp
);
788 Srb
= Stack
->Parameters
.Scsi
.Srb
;
791 Status
= STATUS_UNSUCCESSFUL
;
793 Irp
->IoStatus
.Status
= Status
;
794 Irp
->IoStatus
.Information
= 0;
796 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
801 DPRINT("Srb: %p\n", Srb
);
802 DPRINT("Srb->Function: %lu\n", Srb
->Function
);
803 DPRINT("PathId: %lu TargetId: %lu Lun: %lu\n", Srb
->PathId
, Srb
->TargetId
, Srb
->Lun
);
805 switch (Srb
->Function
)
807 case SRB_FUNCTION_EXECUTE_SCSI
:
808 IoStartPacket(DeviceObject
, Irp
, NULL
, NULL
);
809 return(STATUS_PENDING
);
811 case SRB_FUNCTION_SHUTDOWN
:
812 case SRB_FUNCTION_FLUSH
:
813 if (DeviceExtension
->PortConfig
.CachesData
== TRUE
)
815 IoStartPacket(DeviceObject
, Irp
, NULL
, NULL
);
816 return(STATUS_PENDING
);
820 case SRB_FUNCTION_CLAIM_DEVICE
:
822 PSCSI_ADAPTER_BUS_INFO AdapterInfo
;
823 PSCSI_INQUIRY_DATA UnitInfo
;
824 PINQUIRYDATA InquiryData
;
826 DPRINT(" SRB_FUNCTION_CLAIM_DEVICE\n");
827 DPRINT("PathId: %lu TargetId: %lu Lun: %lu\n", Srb
->PathId
, Srb
->TargetId
, Srb
->Lun
);
829 Srb
->DataBuffer
= NULL
;
831 if (DeviceExtension
->PortBusInfo
!= NULL
)
833 AdapterInfo
= (PSCSI_ADAPTER_BUS_INFO
)DeviceExtension
->PortBusInfo
;
835 if (AdapterInfo
->BusData
[Srb
->PathId
].NumberOfLogicalUnits
== 0)
838 UnitInfo
= (PSCSI_INQUIRY_DATA
)((PUCHAR
)AdapterInfo
+
839 AdapterInfo
->BusData
[Srb
->PathId
].InquiryDataOffset
);
841 while (AdapterInfo
->BusData
[Srb
->PathId
].InquiryDataOffset
)
843 InquiryData
= (PINQUIRYDATA
)UnitInfo
->InquiryData
;
845 if ((UnitInfo
->TargetId
== Srb
->TargetId
) &&
846 (UnitInfo
->Lun
== Srb
->Lun
) &&
847 (UnitInfo
->DeviceClaimed
== FALSE
))
849 UnitInfo
->DeviceClaimed
= TRUE
;
850 DPRINT("Claimed device!\n");
852 /* FIXME: Hack!!!!! */
853 Srb
->DataBuffer
= DeviceObject
;
858 if (UnitInfo
->NextInquiryDataOffset
== 0)
861 UnitInfo
= (PSCSI_INQUIRY_DATA
)((PUCHAR
)AdapterInfo
+ UnitInfo
->NextInquiryDataOffset
);
867 case SRB_FUNCTION_RELEASE_DEVICE
:
869 PSCSI_ADAPTER_BUS_INFO AdapterInfo
;
870 PSCSI_INQUIRY_DATA UnitInfo
;
871 PINQUIRYDATA InquiryData
;
873 DPRINT(" SRB_FUNCTION_RELEASE_DEVICE\n");
874 DPRINT("PathId: %lu TargetId: %lu Lun: %lu\n", Srb
->PathId
, Srb
->TargetId
, Srb
->Lun
);
876 if (DeviceExtension
->PortBusInfo
!= NULL
)
878 AdapterInfo
= (PSCSI_ADAPTER_BUS_INFO
)DeviceExtension
->PortBusInfo
;
880 if (AdapterInfo
->BusData
[Srb
->PathId
].NumberOfLogicalUnits
== 0)
883 UnitInfo
= (PSCSI_INQUIRY_DATA
)((PUCHAR
)AdapterInfo
+
884 AdapterInfo
->BusData
[Srb
->PathId
].InquiryDataOffset
);
886 while (AdapterInfo
->BusData
[Srb
->PathId
].InquiryDataOffset
)
888 InquiryData
= (PINQUIRYDATA
)UnitInfo
->InquiryData
;
890 if ((UnitInfo
->TargetId
== Srb
->TargetId
) &&
891 (UnitInfo
->Lun
== Srb
->Lun
) &&
892 (UnitInfo
->DeviceClaimed
== TRUE
))
894 UnitInfo
->DeviceClaimed
= FALSE
;
895 DPRINT("Released device!\n");
899 if (UnitInfo
->NextInquiryDataOffset
== 0)
902 UnitInfo
= (PSCSI_INQUIRY_DATA
)((PUCHAR
)AdapterInfo
+ UnitInfo
->NextInquiryDataOffset
);
909 DPRINT1("SRB function not implemented (Function %lu)\n", Srb
->Function
);
910 Status
= STATUS_NOT_IMPLEMENTED
;
914 Irp
->IoStatus
.Status
= Status
;
915 Irp
->IoStatus
.Information
= DataSize
;
917 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
923 /**********************************************************************
925 * ScsiPortDeviceControl
928 * Answer requests for device control calls
934 * Standard dispatch arguments
940 static NTSTATUS STDCALL
941 ScsiPortDeviceControl(IN PDEVICE_OBJECT DeviceObject
,
944 PIO_STACK_LOCATION Stack
;
945 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
947 DPRINT("ScsiPortDeviceControl()\n");
949 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
950 Irp
->IoStatus
.Information
= 0;
953 Stack
= IoGetCurrentIrpStackLocation(Irp
);
954 DeviceExtension
= DeviceObject
->DeviceExtension
;
956 switch (Stack
->Parameters
.DeviceIoControl
.IoControlCode
)
958 case IOCTL_SCSI_GET_DUMP_POINTERS
:
960 PDUMP_POINTERS DumpPointers
;
961 DPRINT(" IOCTL_SCSI_GET_DUMP_POINTERS\n");
962 DumpPointers
= (PDUMP_POINTERS
)Irp
->AssociatedIrp
.SystemBuffer
;
963 DumpPointers
->DeviceObject
= DeviceObject
;
965 Irp
->IoStatus
.Information
= sizeof(DUMP_POINTERS
);
968 case IOCTL_SCSI_GET_CAPABILITIES
:
970 DPRINT(" IOCTL_SCSI_GET_CAPABILITIES\n");
972 *((PIO_SCSI_CAPABILITIES
*)Irp
->AssociatedIrp
.SystemBuffer
) =
973 DeviceExtension
->PortCapabilities
;
975 Irp
->IoStatus
.Information
= sizeof(PIO_SCSI_CAPABILITIES
);
979 case IOCTL_SCSI_GET_INQUIRY_DATA
:
981 DPRINT(" IOCTL_SCSI_GET_INQUIRY_DATA\n");
983 /* Copy inquiry data to the port device extension */
984 memcpy(Irp
->AssociatedIrp
.SystemBuffer
,
985 DeviceExtension
->PortBusInfo
,
986 DeviceExtension
->PortBusInfoSize
);
988 DPRINT("BufferSize: %lu\n", DeviceExtension
->PortBusInfoSize
);
989 Irp
->IoStatus
.Information
= DeviceExtension
->PortBusInfoSize
;
994 DPRINT1(" unknown ioctl code: 0x%lX\n",
995 Stack
->Parameters
.DeviceIoControl
.IoControlCode
);
999 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1001 return(STATUS_SUCCESS
);
1006 ScsiPortStartIo(IN PDEVICE_OBJECT DeviceObject
,
1009 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
1010 PIO_STACK_LOCATION IrpStack
;
1013 DPRINT("ScsiPortStartIo() called!\n");
1015 DeviceExtension
= DeviceObject
->DeviceExtension
;
1016 IrpStack
= IoGetCurrentIrpStackLocation(Irp
);
1018 // FIXME: implement the supported functions
1020 switch (IrpStack
->MajorFunction
)
1025 PSCSI_REQUEST_BLOCK Srb
;
1028 DPRINT("IRP_MJ_SCSI\n");
1030 Srb
= IrpStack
->Parameters
.Scsi
.Srb
;
1032 DPRINT("DeviceExtension %p\n", DeviceExtension
);
1034 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1035 Irp
->IoStatus
.Information
= Srb
->DataTransferLength
;
1037 DeviceExtension
->CurrentIrp
= Irp
;
1039 if (!KeSynchronizeExecution(DeviceExtension
->Interrupt
,
1040 ScsiPortStartPacket
,
1043 DPRINT("Synchronization failed!\n");
1045 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
1046 Irp
->IoStatus
.Information
= 0;
1047 IoCompleteRequest(Irp
,
1049 IoStartNextPacket(DeviceObject
,
1052 KeAcquireSpinLock(&DeviceExtension
->IrpLock
, &oldIrql
);
1053 if (DeviceExtension
->IrpFlags
& IRP_FLAG_COMPLETE
)
1055 DeviceExtension
->IrpFlags
&= ~IRP_FLAG_COMPLETE
;
1056 IoCompleteRequest(Irp
,
1060 if (DeviceExtension
->IrpFlags
& IRP_FLAG_NEXT
)
1062 DeviceExtension
->IrpFlags
&= ~IRP_FLAG_NEXT
;
1063 KeReleaseSpinLock(&DeviceExtension
->IrpLock
, oldIrql
);
1064 IoStartNextPacket(DeviceObject
,
1069 KeReleaseSpinLock(&DeviceExtension
->IrpLock
, oldIrql
);
1075 Irp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
1076 Irp
->IoStatus
.Information
= 0;
1077 IoCompleteRequest(Irp
,
1079 IoStartNextPacket(DeviceObject
,
1083 DPRINT("ScsiPortStartIo() done\n");
1087 static BOOLEAN STDCALL
1088 ScsiPortStartPacket(IN OUT PVOID Context
)
1090 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
1091 PIO_STACK_LOCATION IrpStack
;
1092 PSCSI_REQUEST_BLOCK Srb
;
1094 DPRINT("ScsiPortStartPacket() called\n");
1096 DeviceExtension
= (PSCSI_PORT_DEVICE_EXTENSION
)Context
;
1098 IrpStack
= IoGetCurrentIrpStackLocation(DeviceExtension
->CurrentIrp
);
1099 Srb
= IrpStack
->Parameters
.Scsi
.Srb
;
1101 return(DeviceExtension
->HwStartIo(&DeviceExtension
->MiniPortDeviceExtension
,
1106 /**********************************************************************
1108 * ScsiPortCreatePortDevice
1111 * Creates and initializes a SCSI port device object.
1120 * PseudoDeviceExtension
1131 ScsiPortCreatePortDevice(IN PDRIVER_OBJECT DriverObject
,
1132 IN PSCSI_PORT_DEVICE_EXTENSION PseudoDeviceExtension
,
1133 IN ULONG PortNumber
,
1134 IN OUT PSCSI_PORT_DEVICE_EXTENSION
*RealDeviceExtension
)
1136 PSCSI_PORT_DEVICE_EXTENSION PortDeviceExtension
;
1137 PIO_SCSI_CAPABILITIES PortCapabilities
;
1138 PDEVICE_OBJECT PortDeviceObject
;
1139 WCHAR NameBuffer
[80];
1140 UNICODE_STRING DeviceName
;
1141 WCHAR DosNameBuffer
[80];
1142 UNICODE_STRING DosDeviceName
;
1144 ULONG AccessRangeSize
;
1149 DPRINT("ScsiPortCreatePortDevice() called\n");
1151 *RealDeviceExtension
= NULL
;
1153 MappedIrq
= HalGetInterruptVector(PseudoDeviceExtension
->PortConfig
.AdapterInterfaceType
,
1154 PseudoDeviceExtension
->PortConfig
.SystemIoBusNumber
,
1155 PseudoDeviceExtension
->PortConfig
.BusInterruptLevel
,
1156 PseudoDeviceExtension
->PortConfig
.BusInterruptVector
,
1160 /* Create a unicode device name */
1161 swprintf(NameBuffer
,
1162 L
"\\Device\\ScsiPort%lu",
1164 RtlInitUnicodeString(&DeviceName
,
1167 DPRINT("Creating device: %wZ\n", &DeviceName
);
1169 /* Create the port device */
1170 Status
= IoCreateDevice(DriverObject
,
1171 PseudoDeviceExtension
->Length
,
1173 FILE_DEVICE_CONTROLLER
,
1177 if (!NT_SUCCESS(Status
))
1179 DbgPrint("IoCreateDevice call failed! (Status 0x%lX)\n", Status
);
1183 DPRINT("Created device: %wZ\n", &DeviceName
);
1185 /* Set the buffering strategy here... */
1186 PortDeviceObject
->Flags
|= DO_DIRECT_IO
;
1187 PortDeviceObject
->AlignmentRequirement
= FILE_WORD_ALIGNMENT
;
1189 PortDeviceExtension
= PortDeviceObject
->DeviceExtension
;
1191 /* Copy pseudo device extension into the real device extension */
1192 memcpy(PortDeviceExtension
,
1193 PseudoDeviceExtension
,
1194 PseudoDeviceExtension
->Length
);
1196 /* Copy access ranges */
1198 sizeof(ACCESS_RANGE
) * PseudoDeviceExtension
->PortConfig
.NumberOfAccessRanges
;
1199 PortDeviceExtension
->PortConfig
.AccessRanges
= ExAllocatePool(NonPagedPool
,
1201 memcpy(PortDeviceExtension
->PortConfig
.AccessRanges
,
1202 PseudoDeviceExtension
->PortConfig
.AccessRanges
,
1205 /* Copy device base list */
1206 if (IsListEmpty(&PseudoDeviceExtension
->DeviceBaseListHead
))
1208 InitializeListHead(&PortDeviceExtension
->DeviceBaseListHead
);
1212 PseudoDeviceExtension
->DeviceBaseListHead
.Flink
=
1213 PortDeviceExtension
->DeviceBaseListHead
.Flink
;
1214 PseudoDeviceExtension
->DeviceBaseListHead
.Blink
=
1215 PortDeviceExtension
->DeviceBaseListHead
.Blink
;
1216 PortDeviceExtension
->DeviceBaseListHead
.Blink
->Flink
=
1217 &PortDeviceExtension
->DeviceBaseListHead
;
1218 PortDeviceExtension
->DeviceBaseListHead
.Flink
->Blink
=
1219 &PortDeviceExtension
->DeviceBaseListHead
;
1222 PortDeviceExtension
->DeviceObject
= PortDeviceObject
;
1223 PortDeviceExtension
->PortNumber
= PortNumber
;
1225 /* Initialize the spin lock in the controller extension */
1226 KeInitializeSpinLock(&PortDeviceExtension
->IrpLock
);
1227 KeInitializeSpinLock(&PortDeviceExtension
->SpinLock
);
1229 /* Register an interrupt handler for this device */
1230 Status
= IoConnectInterrupt(&PortDeviceExtension
->Interrupt
,
1232 PortDeviceExtension
,
1233 &PortDeviceExtension
->SpinLock
,
1237 PortDeviceExtension
->PortConfig
.InterruptMode
,
1241 if (!NT_SUCCESS(Status
))
1243 DbgPrint("Could not Connect Interrupt %d\n",
1244 PortDeviceExtension
->PortConfig
.BusInterruptVector
);
1248 /* Initialize the DPC object */
1249 IoInitializeDpcRequest(PortDeviceExtension
->DeviceObject
,
1252 /* Initialize the device timer */
1253 PortDeviceExtension
->TimerState
= IDETimerIdle
;
1254 PortDeviceExtension
->TimerCount
= 0;
1255 IoInitializeTimer(PortDeviceExtension
->DeviceObject
,
1257 PortDeviceExtension
);
1259 /* Initialize port capabilities */
1260 PortCapabilities
= ExAllocatePool(NonPagedPool
,
1261 sizeof(IO_SCSI_CAPABILITIES
));
1262 PortDeviceExtension
->PortCapabilities
= PortCapabilities
;
1263 PortCapabilities
->Length
= sizeof(IO_SCSI_CAPABILITIES
);
1264 PortCapabilities
->MaximumTransferLength
=
1265 PortDeviceExtension
->PortConfig
.MaximumTransferLength
;
1266 PortCapabilities
->MaximumPhysicalPages
=
1267 PortCapabilities
->MaximumTransferLength
/ PAGE_SIZE
;
1268 PortCapabilities
->SupportedAsynchronousEvents
= 0; /* FIXME */
1269 PortCapabilities
->AlignmentMask
=
1270 PortDeviceExtension
->PortConfig
.AlignmentMask
;
1271 PortCapabilities
->TaggedQueuing
=
1272 PortDeviceExtension
->PortConfig
.TaggedQueuing
;
1273 PortCapabilities
->AdapterScansDown
=
1274 PortDeviceExtension
->PortConfig
.AdapterScansDown
;
1275 PortCapabilities
->AdapterUsesPio
= TRUE
; /* FIXME */
1277 /* Initialize inquiry data */
1278 PortDeviceExtension
->PortBusInfoSize
= 0;
1279 PortDeviceExtension
->PortBusInfo
= NULL
;
1281 DPRINT("DeviceExtension %p\n", PortDeviceExtension
);
1282 ScsiPortInquire(PortDeviceExtension
);
1285 /* FIXME: Copy more configuration data? */
1288 /* Create the dos device link */
1289 swprintf(DosNameBuffer
,
1292 RtlInitUnicodeString(&DosDeviceName
,
1295 IoCreateSymbolicLink(&DosDeviceName
,
1298 *RealDeviceExtension
= PortDeviceExtension
;
1300 DPRINT("ScsiPortCreatePortDevice() done\n");
1302 return(STATUS_SUCCESS
);
1307 ScsiPortInquire(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
)
1309 PSCSI_ADAPTER_BUS_INFO AdapterInfo
;
1310 PSCSI_INQUIRY_DATA UnitInfo
, PrevUnit
;
1311 SCSI_REQUEST_BLOCK Srb
;
1318 DPRINT("ScsiPortInquire() called\n");
1320 DeviceExtension
->Initializing
= TRUE
;
1322 /* Copy inquiry data to the port device extension */
1323 AdapterInfo
=(PSCSI_ADAPTER_BUS_INFO
)ExAllocatePool(NonPagedPool
, 4096);
1324 RtlZeroMemory(AdapterInfo
, 4096);
1325 AdapterInfo
->NumberOfBuses
= DeviceExtension
->PortConfig
.NumberOfBuses
;
1327 UnitInfo
= (PSCSI_INQUIRY_DATA
)
1328 ((PUCHAR
)AdapterInfo
+ sizeof(SCSI_ADAPTER_BUS_INFO
) +
1329 (sizeof(SCSI_BUS_DATA
) * (AdapterInfo
->NumberOfBuses
- 1)));
1332 sizeof(SCSI_REQUEST_BLOCK
));
1333 Srb
.DataBuffer
= ExAllocatePool(NonPagedPool
, 256);
1334 Srb
.Function
= SRB_FUNCTION_EXECUTE_SCSI
;
1335 Srb
.DataTransferLength
= 256;
1336 Srb
.Cdb
[0] = SCSIOP_INQUIRY
;
1338 for (Bus
= 0; Bus
< AdapterInfo
->NumberOfBuses
; Bus
++)
1342 AdapterInfo
->BusData
[Bus
].InitiatorBusId
=
1343 DeviceExtension
->PortConfig
.InitiatorBusId
[Bus
];
1344 AdapterInfo
->BusData
[Bus
].InquiryDataOffset
=
1345 (ULONG
)((PUCHAR
)UnitInfo
- (PUCHAR
)AdapterInfo
);
1350 for (Target
= 0; Target
< DeviceExtension
->PortConfig
.MaximumNumberOfTargets
; Target
++)
1352 Srb
.TargetId
= Target
;
1354 Srb
.SrbStatus
= SRB_STATUS_SUCCESS
;
1356 Result
= DeviceExtension
->HwStartIo(&DeviceExtension
->MiniPortDeviceExtension
,
1358 DPRINT("Result: %s Srb.SrbStatus %lx\n", (Result
)?"True":"False", Srb
.SrbStatus
);
1360 if (Result
== TRUE
&& Srb
.SrbStatus
== SRB_STATUS_SUCCESS
)
1362 UnitInfo
->PathId
= Bus
;
1363 UnitInfo
->TargetId
= Target
;
1365 UnitInfo
->InquiryDataLength
= INQUIRYDATABUFFERSIZE
;
1366 memcpy(&UnitInfo
->InquiryData
,
1368 INQUIRYDATABUFFERSIZE
);
1369 if (PrevUnit
!= NULL
)
1370 PrevUnit
->NextInquiryDataOffset
= (ULONG
)((PUCHAR
)UnitInfo
-(PUCHAR
)AdapterInfo
);
1371 PrevUnit
= UnitInfo
;
1372 UnitInfo
= (PSCSI_INQUIRY_DATA
)((PUCHAR
)UnitInfo
+ sizeof(SCSI_INQUIRY_DATA
)+INQUIRYDATABUFFERSIZE
-1);
1376 DPRINT("UnitCount: %lu\n", UnitCount
);
1377 AdapterInfo
->BusData
[Bus
].NumberOfLogicalUnits
= UnitCount
;
1379 AdapterInfo
->BusData
[Bus
].InquiryDataOffset
= 0;
1381 DataSize
= (ULONG
)((PUCHAR
)UnitInfo
-(PUCHAR
)AdapterInfo
);
1383 ExFreePool(Srb
.DataBuffer
);
1385 DeviceExtension
->Initializing
= FALSE
;
1387 /* copy inquiry data to the port driver's device extension */
1388 DeviceExtension
->PortBusInfoSize
= DataSize
;
1389 DeviceExtension
->PortBusInfo
= ExAllocatePool(NonPagedPool
,
1391 RtlCopyMemory(DeviceExtension
->PortBusInfo
,
1395 ExFreePool(AdapterInfo
);
1397 DPRINT("ScsiPortInquire() done\n");
1401 static BOOLEAN STDCALL
1402 ScsiPortIsr(IN PKINTERRUPT Interrupt
,
1403 IN PVOID ServiceContext
)
1405 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
1408 DPRINT("ScsiPortIsr() called!\n");
1410 DeviceExtension
= (PSCSI_PORT_DEVICE_EXTENSION
)ServiceContext
;
1412 Result
= DeviceExtension
->HwInterrupt(&DeviceExtension
->MiniPortDeviceExtension
);
1413 if (Result
== FALSE
)
1418 if (DeviceExtension
->IrpFlags
)
1420 IoRequestDpc(DeviceExtension
->DeviceObject
,
1421 DeviceExtension
->CurrentIrp
,
1429 // ScsiPortDpcForIsr
1436 // IN PDEVICE_OBJECT DpcDeviceObject
1438 // IN PVOID DpcContext
1441 ScsiPortDpcForIsr(IN PKDPC Dpc
,
1442 IN PDEVICE_OBJECT DpcDeviceObject
,
1444 IN PVOID DpcContext
)
1446 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
1447 PIO_STACK_LOCATION IrpStack
;
1448 PSCSI_REQUEST_BLOCK Srb
;
1451 DPRINT("ScsiPortDpcForIsr(Dpc %p DpcDeviceObject %p DpcIrp %p DpcContext %p)\n",
1452 Dpc
, DpcDeviceObject
, DpcIrp
, DpcContext
);
1454 DeviceExtension
= (PSCSI_PORT_DEVICE_EXTENSION
)DpcContext
;
1456 KeAcquireSpinLock(&DeviceExtension
->IrpLock
, &oldIrql
);
1457 if (DeviceExtension
->IrpFlags
)
1459 IrpStack
= IoGetCurrentIrpStackLocation(DeviceExtension
->CurrentIrp
);
1460 Srb
= IrpStack
->Parameters
.Scsi
.Srb
;
1462 if (DeviceExtension
->OriginalSrb
!= NULL
)
1464 DPRINT("Got sense data!\n");
1466 DPRINT("Valid: %x\n", DeviceExtension
->InternalSenseData
.Valid
);
1467 DPRINT("ErrorCode: %x\n", DeviceExtension
->InternalSenseData
.ErrorCode
);
1468 DPRINT("SenseKey: %x\n", DeviceExtension
->InternalSenseData
.SenseKey
);
1469 DPRINT("SenseCode: %x\n", DeviceExtension
->InternalSenseData
.AdditionalSenseCode
);
1471 /* Copy sense data */
1472 if (DeviceExtension
->OriginalSrb
->SenseInfoBufferLength
!= 0)
1474 RtlCopyMemory(DeviceExtension
->OriginalSrb
->SenseInfoBuffer
,
1475 &DeviceExtension
->InternalSenseData
,
1476 sizeof(SENSE_DATA
));
1477 DeviceExtension
->OriginalSrb
->SrbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
1480 /* Clear current sense data */
1481 RtlZeroMemory(&DeviceExtension
->InternalSenseData
, sizeof(SENSE_DATA
));
1483 IrpStack
->Parameters
.Scsi
.Srb
= DeviceExtension
->OriginalSrb
;
1484 DeviceExtension
->OriginalSrb
= NULL
;
1486 else if ((SRB_STATUS(Srb
->SrbStatus
) != SRB_STATUS_SUCCESS
) &&
1487 (Srb
->ScsiStatus
== SCSISTAT_CHECK_CONDITION
))
1489 DPRINT("SCSIOP_REQUEST_SENSE required!\n");
1491 DeviceExtension
->OriginalSrb
= Srb
;
1492 IrpStack
->Parameters
.Scsi
.Srb
= ScsiPortInitSenseRequestSrb(DeviceExtension
,
1494 KeReleaseSpinLock(&DeviceExtension
->IrpLock
, oldIrql
);
1495 if (!KeSynchronizeExecution(DeviceExtension
->Interrupt
,
1496 ScsiPortStartPacket
,
1499 DPRINT1("Synchronization failed!\n");
1501 DpcIrp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
1502 DpcIrp
->IoStatus
.Information
= 0;
1503 IoCompleteRequest(DpcIrp
,
1505 IoStartNextPacket(DpcDeviceObject
,
1512 DeviceExtension
->CurrentIrp
= NULL
;
1515 // DpcIrp->IoStatus.Information = 0;
1516 // DpcIrp->IoStatus.Status = STATUS_SUCCESS;
1518 if (DeviceExtension
->IrpFlags
& IRP_FLAG_COMPLETE
)
1520 DeviceExtension
->IrpFlags
&= ~IRP_FLAG_COMPLETE
;
1521 IoCompleteRequest(DpcIrp
, IO_NO_INCREMENT
);
1524 if (DeviceExtension
->IrpFlags
& IRP_FLAG_NEXT
)
1526 DeviceExtension
->IrpFlags
&= ~IRP_FLAG_NEXT
;
1527 KeReleaseSpinLock(&DeviceExtension
->IrpLock
, oldIrql
);
1528 IoStartNextPacket(DpcDeviceObject
, FALSE
);
1532 KeReleaseSpinLock(&DeviceExtension
->IrpLock
, oldIrql
);
1537 KeReleaseSpinLock(&DeviceExtension
->IrpLock
, oldIrql
);
1540 DPRINT("ScsiPortDpcForIsr() done\n");
1546 // This function handles timeouts and other time delayed processing
1551 // IN PDEVICE_OBJECT DeviceObject Device object registered with timer
1552 // IN PVOID Context the Controller extension for the
1553 // controller the device is on
1556 ScsiPortIoTimer(PDEVICE_OBJECT DeviceObject
,
1559 DPRINT1("ScsiPortIoTimer()\n");
1563 static PSCSI_REQUEST_BLOCK
1564 ScsiPortInitSenseRequestSrb(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
1565 PSCSI_REQUEST_BLOCK OriginalSrb
)
1567 PSCSI_REQUEST_BLOCK Srb
;
1570 Srb
= &DeviceExtension
->InternalSrb
;
1573 sizeof(SCSI_REQUEST_BLOCK
));
1575 Srb
->PathId
= OriginalSrb
->PathId
;
1576 Srb
->TargetId
= OriginalSrb
->TargetId
;
1577 Srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
1578 Srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
1579 Srb
->SrbFlags
= SRB_FLAGS_DATA_IN
| SRB_FLAGS_DISABLE_SYNCH_TRANSFER
;
1581 Srb
->TimeOutValue
= 4;
1584 Srb
->DataBuffer
= &DeviceExtension
->InternalSenseData
;
1585 Srb
->DataTransferLength
= sizeof(SENSE_DATA
);
1587 Cdb
= (PCDB
)Srb
->Cdb
;
1588 Cdb
->CDB6INQUIRY
.OperationCode
= SCSIOP_REQUEST_SENSE
;
1589 Cdb
->CDB6INQUIRY
.AllocationLength
= sizeof(SENSE_DATA
);
1596 ScsiPortFreeSenseRequestSrb(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
)
1598 DeviceExtension
->OriginalSrb
= NULL
;
1602 /**********************************************************************
1604 * ScsiPortBuildDeviceMap
1607 * Builds the registry device map of all device which are attached
1608 * to the given SCSI HBA port. The device map is located at:
1609 * \Registry\Machine\DeviceMap\Scsi
1619 * Name of registry driver service key.
1626 ScsiPortBuildDeviceMap(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
1627 PUNICODE_STRING RegistryPath
)
1629 OBJECT_ATTRIBUTES ObjectAttributes
;
1630 UNICODE_STRING KeyName
;
1631 UNICODE_STRING ValueName
;
1632 WCHAR NameBuffer
[64];
1637 HANDLE ScsiInitiatorKey
;
1638 HANDLE ScsiTargetKey
;
1641 UCHAR CurrentTarget
;
1642 PSCSI_ADAPTER_BUS_INFO AdapterInfo
;
1643 PSCSI_INQUIRY_DATA UnitInfo
;
1644 PINQUIRYDATA InquiryData
;
1650 DPRINT("ScsiPortBuildDeviceMap() called\n");
1652 if (DeviceExtension
== NULL
|| RegistryPath
== NULL
)
1654 DPRINT1("Invalid parameter\n");
1655 return(STATUS_INVALID_PARAMETER
);
1658 /* Open or create the 'Scsi' subkey */
1659 RtlInitUnicodeStringFromLiteral(&KeyName
,
1660 L
"\\Registry\\Machine\\Hardware\\DeviceMap\\Scsi");
1661 InitializeObjectAttributes(&ObjectAttributes
,
1663 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
,
1666 Status
= ZwCreateKey(&ScsiKey
,
1671 REG_OPTION_VOLATILE
,
1673 if (!NT_SUCCESS(Status
))
1675 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status
);
1679 /* Create new 'Scsi Port X' subkey */
1680 DPRINT("Scsi Port %lu\n",
1681 DeviceExtension
->PortNumber
);
1683 swprintf(NameBuffer
,
1685 DeviceExtension
->PortNumber
);
1686 RtlInitUnicodeString(&KeyName
,
1688 InitializeObjectAttributes(&ObjectAttributes
,
1693 Status
= ZwCreateKey(&ScsiPortKey
,
1698 REG_OPTION_VOLATILE
,
1701 if (!NT_SUCCESS(Status
))
1703 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status
);
1708 * Create port-specific values
1711 /* Set 'DMA Enabled' (REG_DWORD) value */
1712 UlongData
= (ULONG
)!DeviceExtension
->PortCapabilities
->AdapterUsesPio
;
1713 DPRINT(" DMA Enabled = %s\n", (UlongData
) ? "TRUE" : "FALSE");
1714 RtlInitUnicodeString(&ValueName
,
1716 Status
= ZwSetValueKey(ScsiPortKey
,
1722 if (!NT_SUCCESS(Status
))
1724 DPRINT("ZwSetValueKey('DMA Enabled') failed (Status %lx)\n", Status
);
1725 ZwClose(ScsiPortKey
);
1729 /* Set 'Driver' (REG_SZ) value */
1730 DriverName
= wcsrchr(RegistryPath
->Buffer
, L
'\\') + 1;
1731 RtlInitUnicodeString(&ValueName
,
1733 Status
= ZwSetValueKey(ScsiPortKey
,
1738 (wcslen(DriverName
) + 1) * sizeof(WCHAR
));
1739 if (!NT_SUCCESS(Status
))
1741 DPRINT("ZwSetValueKey('Driver') failed (Status %lx)\n", Status
);
1742 ZwClose(ScsiPortKey
);
1746 /* Set 'Interrupt' (REG_DWORD) value (NT4 only) */
1747 UlongData
= (ULONG
)DeviceExtension
->PortConfig
.BusInterruptLevel
;
1748 DPRINT(" Interrupt = %lu\n", UlongData
);
1749 RtlInitUnicodeString(&ValueName
,
1751 Status
= ZwSetValueKey(ScsiPortKey
,
1757 if (!NT_SUCCESS(Status
))
1759 DPRINT("ZwSetValueKey('Interrupt') failed (Status %lx)\n", Status
);
1760 ZwClose(ScsiPortKey
);
1764 /* Set 'IOAddress' (REG_DWORD) value (NT4 only) */
1765 UlongData
= ScsiPortConvertPhysicalAddressToUlong(DeviceExtension
->PortConfig
.AccessRanges
[0].RangeStart
);
1766 DPRINT(" IOAddress = %lx\n", UlongData
);
1767 RtlInitUnicodeString(&ValueName
,
1769 Status
= ZwSetValueKey(ScsiPortKey
,
1775 if (!NT_SUCCESS(Status
))
1777 DPRINT("ZwSetValueKey('IOAddress') failed (Status %lx)\n", Status
);
1778 ZwClose(ScsiPortKey
);
1782 /* Enumerate buses */
1783 for (BusNumber
= 0; BusNumber
< DeviceExtension
->PortConfig
.NumberOfBuses
; BusNumber
++)
1785 /* Create 'Scsi Bus X' key */
1786 DPRINT(" Scsi Bus %lu\n", BusNumber
);
1787 swprintf(NameBuffer
,
1790 RtlInitUnicodeString(&KeyName
,
1792 InitializeObjectAttributes(&ObjectAttributes
,
1797 Status
= ZwCreateKey(&ScsiBusKey
,
1802 REG_OPTION_VOLATILE
,
1804 if (!NT_SUCCESS(Status
))
1806 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status
);
1807 ZwClose(ScsiPortKey
);
1811 /* Create 'Initiator Id X' key */
1812 DPRINT(" Initiator Id %u\n",
1813 DeviceExtension
->PortConfig
.InitiatorBusId
[BusNumber
]);
1814 swprintf(NameBuffer
,
1816 DeviceExtension
->PortConfig
.InitiatorBusId
[BusNumber
]);
1817 RtlInitUnicodeString(&KeyName
,
1819 InitializeObjectAttributes(&ObjectAttributes
,
1824 Status
= ZwCreateKey(&ScsiInitiatorKey
,
1829 REG_OPTION_VOLATILE
,
1831 if (!NT_SUCCESS(Status
))
1833 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status
);
1834 ZwClose(ScsiBusKey
);
1835 ZwClose(ScsiPortKey
);
1839 /* FIXME: Are there any initiator values (??) */
1841 ZwClose(ScsiInitiatorKey
);
1844 /* Enumerate targets */
1845 CurrentTarget
= (UCHAR
)-1;
1846 ScsiTargetKey
= NULL
;
1847 AdapterInfo
= (PSCSI_ADAPTER_BUS_INFO
)DeviceExtension
->PortBusInfo
;
1848 if (AdapterInfo
->BusData
[BusNumber
].NumberOfLogicalUnits
!= 0)
1850 UnitInfo
= (PSCSI_INQUIRY_DATA
)((PUCHAR
)AdapterInfo
+
1851 AdapterInfo
->BusData
[BusNumber
].InquiryDataOffset
);
1853 while (AdapterInfo
->BusData
[BusNumber
].InquiryDataOffset
)
1855 if (UnitInfo
->TargetId
!= CurrentTarget
)
1857 /* Close old target key */
1858 if (ScsiTargetKey
!= NULL
)
1860 ZwClose(ScsiTargetKey
);
1861 ScsiTargetKey
= NULL
;
1864 /* Create 'Target Id X' key */
1865 DPRINT(" Target Id %u\n",
1866 UnitInfo
->TargetId
);
1867 swprintf(NameBuffer
,
1869 UnitInfo
->TargetId
);
1870 RtlInitUnicodeString(&KeyName
,
1872 InitializeObjectAttributes(&ObjectAttributes
,
1877 Status
= ZwCreateKey(&ScsiTargetKey
,
1882 REG_OPTION_VOLATILE
,
1884 if (!NT_SUCCESS(Status
))
1886 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status
);
1887 ZwClose(ScsiBusKey
);
1888 ZwClose(ScsiPortKey
);
1892 CurrentTarget
= UnitInfo
->TargetId
;
1895 /* Create 'Logical Unit Id X' key */
1896 DPRINT(" Logical Unit Id %u\n",
1898 swprintf(NameBuffer
,
1899 L
"Logical Unit Id %u",
1901 RtlInitUnicodeString(&KeyName
,
1903 InitializeObjectAttributes(&ObjectAttributes
,
1908 Status
= ZwCreateKey(&ScsiLunKey
,
1913 REG_OPTION_VOLATILE
,
1915 if (!NT_SUCCESS(Status
))
1917 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status
);
1918 ZwClose(ScsiTargetKey
);
1919 ZwClose(ScsiBusKey
);
1920 ZwClose(ScsiPortKey
);
1924 /* Set values for logical unit */
1925 InquiryData
= (PINQUIRYDATA
)UnitInfo
->InquiryData
;
1927 /* Set 'Identifier' (REG_SZ) value */
1928 swprintf(NameBuffer
,
1930 InquiryData
->VendorId
,
1931 InquiryData
->ProductId
,
1932 InquiryData
->ProductRevisionLevel
);
1933 DPRINT(" Identifier = '%S'\n",
1935 RtlInitUnicodeString(&ValueName
,
1937 Status
= ZwSetValueKey(ScsiLunKey
,
1942 (wcslen(NameBuffer
) + 1) * sizeof(WCHAR
));
1943 if (!NT_SUCCESS(Status
))
1945 DPRINT("ZwSetValueKey('Identifier') failed (Status %lx)\n", Status
);
1946 ZwClose(ScsiLunKey
);
1947 ZwClose(ScsiTargetKey
);
1948 ZwClose(ScsiBusKey
);
1949 ZwClose(ScsiPortKey
);
1953 /* Set 'Type' (REG_SZ) value */
1954 switch (InquiryData
->DeviceType
)
1957 TypeName
= L
"DiskPeripheral";
1960 TypeName
= L
"TapePeripheral";
1963 TypeName
= L
"PrinterPeripheral";
1966 TypeName
= L
"WormPeripheral";
1969 TypeName
= L
"CdRomPeripheral";
1972 TypeName
= L
"ScannerPeripheral";
1975 TypeName
= L
"OpticalDiskPeripheral";
1978 TypeName
= L
"MediumChangerPeripheral";
1981 TypeName
= L
"CommunicationPeripheral";
1984 TypeName
= L
"OtherPeripheral";
1987 DPRINT(" Type = '%S'\n", TypeName
);
1988 RtlInitUnicodeString(&ValueName
,
1990 Status
= ZwSetValueKey(ScsiLunKey
,
1995 (wcslen(TypeName
) + 1) * sizeof(WCHAR
));
1996 if (!NT_SUCCESS(Status
))
1998 DPRINT("ZwSetValueKey('Type') failed (Status %lx)\n", Status
);
1999 ZwClose(ScsiLunKey
);
2000 ZwClose(ScsiTargetKey
);
2001 ZwClose(ScsiBusKey
);
2002 ZwClose(ScsiPortKey
);
2006 ZwClose(ScsiLunKey
);
2008 if (UnitInfo
->NextInquiryDataOffset
== 0)
2011 UnitInfo
= (PSCSI_INQUIRY_DATA
)((PUCHAR
)AdapterInfo
+
2012 UnitInfo
->NextInquiryDataOffset
);
2015 /* Close old target key */
2016 if (ScsiTargetKey
!= NULL
)
2018 ZwClose(ScsiTargetKey
);
2019 ScsiTargetKey
= NULL
;
2023 ZwClose(ScsiBusKey
);
2026 ZwClose(ScsiPortKey
);
2028 DPRINT("ScsiPortBuildDeviceMap() done\n");