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.51 2004/03/24 16:21:59 navaraf 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>
34 #include <rosrtl/string.h>
40 #define VERSION "0.0.1"
42 #include "scsiport_int.h"
44 /* #define USE_DEVICE_QUEUES */
46 /* TYPES *********************************************************************/
48 #define IRP_FLAG_COMPLETE 0x00000001
49 #define IRP_FLAG_NEXT 0x00000002
50 #define IRP_FLAG_NEXT_LU 0x00000004
53 /* GLOBALS *******************************************************************/
56 SpiGetPciConfigData (IN
struct _HW_INITIALIZATION_DATA
*HwInitializationData
,
57 IN OUT PPORT_CONFIGURATION_INFORMATION PortConfig
,
59 IN OUT PPCI_SLOT_NUMBER NextSlotNumber
);
61 static NTSTATUS STDCALL
62 ScsiPortCreateClose(IN PDEVICE_OBJECT DeviceObject
,
65 static NTSTATUS STDCALL
66 ScsiPortDispatchScsi(IN PDEVICE_OBJECT DeviceObject
,
69 static NTSTATUS STDCALL
70 ScsiPortDeviceControl(IN PDEVICE_OBJECT DeviceObject
,
74 ScsiPortStartIo(IN PDEVICE_OBJECT DeviceObject
,
77 static BOOLEAN STDCALL
78 ScsiPortStartPacket(IN OUT PVOID Context
);
81 static PSCSI_PORT_LUN_EXTENSION
82 SpiAllocateLunExtension (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
88 SpiRemoveLunExtension (IN PSCSI_PORT_LUN_EXTENSION LunExtension
);
90 static PSCSI_PORT_LUN_EXTENSION
91 SpiGetLunExtension (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
97 SpiSendInquiry (IN PDEVICE_OBJECT DeviceObject
,
98 IN OUT PSCSI_REQUEST_BLOCK Srb
);
101 SpiScanAdapter (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
);
104 SpiGetInquiryData (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
105 OUT PSCSI_ADAPTER_BUS_INFO AdapterBusInfo
);
107 static BOOLEAN STDCALL
108 ScsiPortIsr(IN PKINTERRUPT Interrupt
,
109 IN PVOID ServiceContext
);
112 ScsiPortDpcForIsr(IN PKDPC Dpc
,
113 IN PDEVICE_OBJECT DpcDeviceObject
,
115 IN PVOID DpcContext
);
118 ScsiPortIoTimer(PDEVICE_OBJECT DeviceObject
,
121 static PSCSI_REQUEST_BLOCK
122 ScsiPortInitSenseRequestSrb(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
123 PSCSI_REQUEST_BLOCK OriginalSrb
);
126 ScsiPortFreeSenseRequestSrb(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
);
129 SpiBuildDeviceMap (PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
130 PUNICODE_STRING RegistryPath
);
133 /* FUNCTIONS *****************************************************************/
135 /**********************************************************************
140 * This function initializes the driver.
147 * System allocated Driver Object for this driver.
150 * Name of registry driver service key.
157 DriverEntry(IN PDRIVER_OBJECT DriverObject
,
158 IN PUNICODE_STRING RegistryPath
)
160 DPRINT("ScsiPort Driver %s\n", VERSION
);
161 return(STATUS_SUCCESS
);
165 /**********************************************************************
170 * Prints debugging messages.
177 * Debug level of the given message.
180 * Pointer to printf()-compatible format string.
183 Additional output data (see printf()).
192 ScsiDebugPrint(IN ULONG DebugPrintLevel
,
193 IN PCHAR DebugMessage
,
200 if (DebugPrintLevel
> InternalDebugLevel
)
204 va_start(ap
, DebugMessage
);
205 vsprintf(Buffer
, DebugMessage
, ap
);
216 ScsiPortCompleteRequest(IN PVOID HwDeviceExtension
,
222 DPRINT("ScsiPortCompleteRequest()\n");
231 ScsiPortConvertPhysicalAddressToUlong(IN SCSI_PHYSICAL_ADDRESS Address
)
233 DPRINT("ScsiPortConvertPhysicalAddressToUlong()\n");
234 return(Address
.u
.LowPart
);
242 ScsiPortFlushDma(IN PVOID HwDeviceExtension
)
244 DPRINT("ScsiPortFlushDma()\n");
253 ScsiPortFreeDeviceBase(IN PVOID HwDeviceExtension
,
254 IN PVOID MappedAddress
)
256 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
257 PSCSI_PORT_DEVICE_BASE DeviceBase
;
260 DPRINT("ScsiPortFreeDeviceBase() called\n");
262 DeviceExtension
= CONTAINING_RECORD(HwDeviceExtension
,
263 SCSI_PORT_DEVICE_EXTENSION
,
264 MiniPortDeviceExtension
);
265 if (IsListEmpty(&DeviceExtension
->DeviceBaseListHead
))
268 Entry
= DeviceExtension
->DeviceBaseListHead
.Flink
;
269 while (Entry
!= &DeviceExtension
->DeviceBaseListHead
)
271 DeviceBase
= CONTAINING_RECORD(Entry
,
272 SCSI_PORT_DEVICE_BASE
,
274 if (DeviceBase
->MappedAddress
== MappedAddress
)
276 MmUnmapIoSpace(DeviceBase
->MappedAddress
,
277 DeviceBase
->NumberOfBytes
);
278 RemoveEntryList(Entry
);
279 ExFreePool(DeviceBase
);
284 Entry
= Entry
->Flink
;
293 ScsiPortGetBusData(IN PVOID DeviceExtension
,
294 IN ULONG BusDataType
,
295 IN ULONG SystemIoBusNumber
,
300 return(HalGetBusData(BusDataType
,
312 ScsiPortGetDeviceBase(IN PVOID HwDeviceExtension
,
313 IN INTERFACE_TYPE BusType
,
314 IN ULONG SystemIoBusNumber
,
315 IN SCSI_PHYSICAL_ADDRESS IoAddress
,
316 IN ULONG NumberOfBytes
,
317 IN BOOLEAN InIoSpace
)
319 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
320 PHYSICAL_ADDRESS TranslatedAddress
;
321 PSCSI_PORT_DEVICE_BASE DeviceBase
;
325 DPRINT ("ScsiPortGetDeviceBase() called\n");
327 AddressSpace
= (ULONG
)InIoSpace
;
328 if (HalTranslateBusAddress(BusType
,
332 &TranslatedAddress
) == FALSE
)
336 if (AddressSpace
!= 0)
337 return((PVOID
)TranslatedAddress
.u
.LowPart
);
339 MappedAddress
= MmMapIoSpace(TranslatedAddress
,
343 DeviceBase
= ExAllocatePool(NonPagedPool
,
344 sizeof(SCSI_PORT_DEVICE_BASE
));
345 if (DeviceBase
== NULL
)
346 return(MappedAddress
);
348 DeviceBase
->MappedAddress
= MappedAddress
;
349 DeviceBase
->NumberOfBytes
= NumberOfBytes
;
350 DeviceBase
->IoAddress
= IoAddress
;
351 DeviceBase
->SystemIoBusNumber
= SystemIoBusNumber
;
353 DeviceExtension
= CONTAINING_RECORD(HwDeviceExtension
,
354 SCSI_PORT_DEVICE_EXTENSION
,
355 MiniPortDeviceExtension
);
357 InsertHeadList(&DeviceExtension
->DeviceBaseListHead
,
360 return(MappedAddress
);
368 ScsiPortGetLogicalUnit(IN PVOID HwDeviceExtension
,
373 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
374 PSCSI_PORT_LUN_EXTENSION LunExtension
;
377 DPRINT("ScsiPortGetLogicalUnit() called\n");
379 DeviceExtension
= CONTAINING_RECORD(HwDeviceExtension
,
380 SCSI_PORT_DEVICE_EXTENSION
,
381 MiniPortDeviceExtension
);
382 if (IsListEmpty(&DeviceExtension
->LunExtensionListHead
))
385 Entry
= DeviceExtension
->LunExtensionListHead
.Flink
;
386 while (Entry
!= &DeviceExtension
->LunExtensionListHead
)
388 LunExtension
= CONTAINING_RECORD(Entry
,
389 SCSI_PORT_LUN_EXTENSION
,
391 if (LunExtension
->PathId
== PathId
&&
392 LunExtension
->TargetId
== TargetId
&&
393 LunExtension
->Lun
== Lun
)
395 return (PVOID
)&LunExtension
->MiniportLunExtension
;
398 Entry
= Entry
->Flink
;
408 SCSI_PHYSICAL_ADDRESS STDCALL
409 ScsiPortGetPhysicalAddress(IN PVOID HwDeviceExtension
,
410 IN PSCSI_REQUEST_BLOCK Srb OPTIONAL
,
411 IN PVOID VirtualAddress
,
414 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
415 SCSI_PHYSICAL_ADDRESS PhysicalAddress
;
416 SCSI_PHYSICAL_ADDRESS NextPhysicalAddress
;
417 ULONG BufferLength
= 0;
421 DPRINT("ScsiPortGetPhysicalAddress(%p %p %p %p)\n",
422 HwDeviceExtension
, Srb
, VirtualAddress
, Length
);
424 DeviceExtension
= CONTAINING_RECORD(HwDeviceExtension
,
425 SCSI_PORT_DEVICE_EXTENSION
,
426 MiniPortDeviceExtension
);
432 if ((ULONG_PTR
)DeviceExtension
->VirtualAddress
> (ULONG_PTR
)VirtualAddress
)
434 PhysicalAddress
.QuadPart
= 0ULL;
435 return PhysicalAddress
;
438 Offset
= (ULONG_PTR
)VirtualAddress
- (ULONG_PTR
)DeviceExtension
->VirtualAddress
;
439 if (Offset
>= DeviceExtension
->CommonBufferLength
)
441 PhysicalAddress
.QuadPart
= 0ULL;
442 return PhysicalAddress
;
445 PhysicalAddress
.QuadPart
=
446 DeviceExtension
->PhysicalAddress
.QuadPart
+ (ULONGLONG
)Offset
;
447 BufferLength
= DeviceExtension
->CommonBufferLength
- Offset
;
451 EndAddress
= Srb
->DataBuffer
+ Srb
->DataTransferLength
;
452 if (VirtualAddress
== NULL
)
454 VirtualAddress
= Srb
->DataBuffer
;
456 else if (VirtualAddress
< Srb
->DataBuffer
|| VirtualAddress
>= EndAddress
)
458 PhysicalAddress
.QuadPart
= 0LL;
459 return PhysicalAddress
;
462 PhysicalAddress
= MmGetPhysicalAddress(VirtualAddress
);
463 if (PhysicalAddress
.QuadPart
== 0LL)
465 return PhysicalAddress
;
468 Offset
= (ULONG_PTR
)VirtualAddress
& (PAGE_SIZE
- 1);
472 * MmGetPhysicalAddress doesn't return the offset within the page.
473 * We must set the correct offset.
475 PhysicalAddress
.u
.LowPart
= (PhysicalAddress
.u
.LowPart
& ~(PAGE_SIZE
- 1)) + Offset
;
477 BufferLength
+= PAGE_SIZE
- Offset
;
478 while (VirtualAddress
+ BufferLength
< EndAddress
)
480 NextPhysicalAddress
= MmGetPhysicalAddress(VirtualAddress
+ BufferLength
);
481 if (PhysicalAddress
.QuadPart
+ (ULONGLONG
)BufferLength
!= NextPhysicalAddress
.QuadPart
)
485 BufferLength
+= PAGE_SIZE
;
487 if (VirtualAddress
+ BufferLength
>= EndAddress
)
489 BufferLength
= EndAddress
- VirtualAddress
;
493 *Length
= BufferLength
;
495 return PhysicalAddress
;
502 PSCSI_REQUEST_BLOCK STDCALL
503 ScsiPortGetSrb(IN PVOID DeviceExtension
,
509 DPRINT1("ScsiPortGetSrb() unimplemented\n");
519 ScsiPortGetUncachedExtension(IN PVOID HwDeviceExtension
,
520 IN PPORT_CONFIGURATION_INFORMATION ConfigInfo
,
521 IN ULONG NumberOfBytes
)
523 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
524 DEVICE_DESCRIPTION DeviceDescription
;
526 DPRINT("ScsiPortGetUncachedExtension(%p %p %lu)\n",
527 HwDeviceExtension
, ConfigInfo
, NumberOfBytes
);
529 DeviceExtension
= CONTAINING_RECORD(HwDeviceExtension
,
530 SCSI_PORT_DEVICE_EXTENSION
,
531 MiniPortDeviceExtension
);
533 /* Check for allocated common DMA buffer */
534 if (DeviceExtension
->VirtualAddress
!= NULL
)
536 DPRINT1("The HBA has already got a common DMA buffer!\n");
540 /* Check for DMA adapter object */
541 if (DeviceExtension
->AdapterObject
== NULL
)
543 /* Initialize DMA adapter description */
544 RtlZeroMemory(&DeviceDescription
,
545 sizeof(DEVICE_DESCRIPTION
));
546 DeviceDescription
.Version
= DEVICE_DESCRIPTION_VERSION
;
547 DeviceDescription
.Master
= ConfigInfo
->Master
;
548 DeviceDescription
.ScatterGather
= ConfigInfo
->ScatterGather
;
549 DeviceDescription
.DemandMode
= ConfigInfo
->DemandMode
;
550 DeviceDescription
.Dma32BitAddresses
= ConfigInfo
->Dma32BitAddresses
;
551 DeviceDescription
.BusNumber
= ConfigInfo
->SystemIoBusNumber
;
552 DeviceDescription
.DmaChannel
= ConfigInfo
->DmaChannel
;
553 DeviceDescription
.InterfaceType
= ConfigInfo
->AdapterInterfaceType
;
554 DeviceDescription
.DmaWidth
= ConfigInfo
->DmaWidth
;
555 DeviceDescription
.DmaSpeed
= ConfigInfo
->DmaSpeed
;
556 DeviceDescription
.MaximumLength
= ConfigInfo
->MaximumTransferLength
;
557 DeviceDescription
.DmaPort
= ConfigInfo
->DmaPort
;
559 /* Get a DMA adapter object */
560 DeviceExtension
->AdapterObject
= HalGetAdapter(&DeviceDescription
,
561 &DeviceExtension
->MapRegisterCount
);
562 if (DeviceExtension
->AdapterObject
== NULL
)
564 DPRINT1("HalGetAdapter() failed\n");
569 /* Allocate a common DMA buffer */
570 DeviceExtension
->CommonBufferLength
=
571 NumberOfBytes
+ DeviceExtension
->SrbExtensionSize
;
572 DeviceExtension
->VirtualAddress
=
573 HalAllocateCommonBuffer(DeviceExtension
->AdapterObject
,
574 DeviceExtension
->CommonBufferLength
,
575 &DeviceExtension
->PhysicalAddress
,
577 if (DeviceExtension
->VirtualAddress
== NULL
)
579 DPRINT1("HalAllocateCommonBuffer() failed!\n");
580 DeviceExtension
->CommonBufferLength
= 0;
584 return (PVOID
)((ULONG_PTR
)DeviceExtension
->VirtualAddress
+
585 DeviceExtension
->SrbExtensionSize
);
593 ScsiPortGetVirtualAddress(IN PVOID HwDeviceExtension
,
594 IN SCSI_PHYSICAL_ADDRESS PhysicalAddress
)
596 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
599 DPRINT("ScsiPortGetVirtualAddress(%p %I64x)\n",
600 HwDeviceExtension
, PhysicalAddress
.QuadPart
);
602 DeviceExtension
= CONTAINING_RECORD(HwDeviceExtension
,
603 SCSI_PORT_DEVICE_EXTENSION
,
604 MiniPortDeviceExtension
);
606 if (DeviceExtension
->PhysicalAddress
.QuadPart
> PhysicalAddress
.QuadPart
)
609 Offset
= (ULONG
)(PhysicalAddress
.QuadPart
- DeviceExtension
->PhysicalAddress
.QuadPart
);
610 if (Offset
>= DeviceExtension
->CommonBufferLength
)
613 return (PVOID
)((ULONG_PTR
)DeviceExtension
->VirtualAddress
+ Offset
);
617 /**********************************************************************
622 * Initializes SCSI port driver specific data.
629 * Pointer to the miniport driver's driver object.
632 * Pointer to the miniport driver's registry path.
634 * HwInitializationData
635 * Pointer to port driver specific configuration data.
638 Miniport driver specific context.
647 ScsiPortInitialize(IN PVOID Argument1
,
649 IN
struct _HW_INITIALIZATION_DATA
*HwInitializationData
,
652 PDRIVER_OBJECT DriverObject
= (PDRIVER_OBJECT
)Argument1
;
653 // PUNICODE_STRING RegistryPath = (PUNICODE_STRING)Argument2;
654 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
655 PCONFIGURATION_INFORMATION SystemConfig
;
656 PPORT_CONFIGURATION_INFORMATION PortConfig
;
657 ULONG DeviceExtensionSize
;
658 ULONG PortConfigSize
;
660 BOOLEAN DeviceFound
= FALSE
;
666 PCI_SLOT_NUMBER SlotNumber
;
668 PDEVICE_OBJECT PortDeviceObject
;
669 WCHAR NameBuffer
[80];
670 UNICODE_STRING DeviceName
;
671 WCHAR DosNameBuffer
[80];
672 UNICODE_STRING DosDeviceName
;
673 PIO_SCSI_CAPABILITIES PortCapabilities
;
679 DPRINT ("ScsiPortInitialize() called!\n");
681 if ((HwInitializationData
->HwInitialize
== NULL
) ||
682 (HwInitializationData
->HwStartIo
== NULL
) ||
683 (HwInitializationData
->HwInterrupt
== NULL
) ||
684 (HwInitializationData
->HwFindAdapter
== NULL
) ||
685 (HwInitializationData
->HwResetBus
== NULL
))
686 return(STATUS_INVALID_PARAMETER
);
688 DriverObject
->DriverStartIo
= ScsiPortStartIo
;
689 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = ScsiPortCreateClose
;
690 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = ScsiPortCreateClose
;
691 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = ScsiPortDeviceControl
;
692 DriverObject
->MajorFunction
[IRP_MJ_SCSI
] = ScsiPortDispatchScsi
;
694 SystemConfig
= IoGetConfigurationInformation();
696 DeviceExtensionSize
= sizeof(SCSI_PORT_DEVICE_EXTENSION
) +
697 HwInitializationData
->DeviceExtensionSize
;
698 PortConfigSize
= sizeof(PORT_CONFIGURATION_INFORMATION
) +
699 HwInitializationData
->NumberOfAccessRanges
* sizeof(ACCESS_RANGE
);
702 MaxBus
= (HwInitializationData
->AdapterInterfaceType
== PCIBus
) ? 8 : 1;
703 DPRINT("MaxBus: %lu\n", MaxBus
);
705 PortDeviceObject
= NULL
;
707 SlotNumber
.u
.AsULONG
= 0;
710 /* Create a unicode device name */
711 swprintf (NameBuffer
,
712 L
"\\Device\\ScsiPort%lu",
713 SystemConfig
->ScsiPortCount
);
714 RtlInitUnicodeString (&DeviceName
,
717 DPRINT("Creating device: %wZ\n", &DeviceName
);
719 /* Create the port device */
720 Status
= IoCreateDevice (DriverObject
,
723 FILE_DEVICE_CONTROLLER
,
727 if (!NT_SUCCESS(Status
))
729 DbgPrint ("IoCreateDevice call failed! (Status 0x%lX)\n", Status
);
730 PortDeviceObject
= NULL
;
734 DPRINT ("Created device: %wZ (%p)\n", &DeviceName
, PortDeviceObject
);
736 /* Set the buffering strategy here... */
737 PortDeviceObject
->Flags
|= DO_DIRECT_IO
;
738 PortDeviceObject
->AlignmentRequirement
= FILE_WORD_ALIGNMENT
;
740 DeviceExtension
= PortDeviceObject
->DeviceExtension
;
741 DeviceExtension
->Length
= DeviceExtensionSize
;
742 DeviceExtension
->DeviceObject
= PortDeviceObject
;
743 DeviceExtension
->PortNumber
= SystemConfig
->ScsiPortCount
;
745 DeviceExtension
->MiniPortExtensionSize
= HwInitializationData
->DeviceExtensionSize
;
746 DeviceExtension
->LunExtensionSize
= HwInitializationData
->SpecificLuExtensionSize
;
747 DeviceExtension
->SrbExtensionSize
= HwInitializationData
->SrbExtensionSize
;
748 DeviceExtension
->HwStartIo
= HwInitializationData
->HwStartIo
;
749 DeviceExtension
->HwInterrupt
= HwInitializationData
->HwInterrupt
;
752 DeviceExtension
->AdapterObject
= NULL
;
753 DeviceExtension
->MapRegisterCount
= 0;
754 DeviceExtension
->PhysicalAddress
.QuadPart
= 0ULL;
755 DeviceExtension
->VirtualAddress
= NULL
;
756 DeviceExtension
->CommonBufferLength
= 0;
759 /* Initialize the device base list */
760 InitializeListHead (&DeviceExtension
->DeviceBaseListHead
);
762 /* Initialize LUN-Extension list */
763 InitializeListHead (&DeviceExtension
->LunExtensionListHead
);
765 /* Initialize the spin lock in the controller extension */
766 KeInitializeSpinLock (&DeviceExtension
->IrpLock
);
767 KeInitializeSpinLock (&DeviceExtension
->SpinLock
);
769 /* Initialize the DPC object */
770 IoInitializeDpcRequest (PortDeviceObject
,
773 /* Initialize the device timer */
774 DeviceExtension
->TimerState
= IDETimerIdle
;
775 DeviceExtension
->TimerCount
= 0;
776 IoInitializeTimer (PortDeviceObject
,
780 /* Allocate and initialize port configuration info */
781 DeviceExtension
->PortConfig
= ExAllocatePool (NonPagedPool
,
783 if (DeviceExtension
->PortConfig
== NULL
)
785 Status
= STATUS_INSUFFICIENT_RESOURCES
;
788 RtlZeroMemory (DeviceExtension
->PortConfig
,
791 PortConfig
= DeviceExtension
->PortConfig
;
792 PortConfig
->Length
= sizeof(PORT_CONFIGURATION_INFORMATION
);
793 PortConfig
->SystemIoBusNumber
= BusNumber
;
794 PortConfig
->AdapterInterfaceType
= HwInitializationData
->AdapterInterfaceType
;
795 PortConfig
->InterruptMode
=
796 (PortConfig
->AdapterInterfaceType
== PCIBus
) ? LevelSensitive
: Latched
;
797 PortConfig
->MaximumTransferLength
= SP_UNINITIALIZED_VALUE
;
798 PortConfig
->NumberOfPhysicalBreaks
= SP_UNINITIALIZED_VALUE
;
799 PortConfig
->DmaChannel
= SP_UNINITIALIZED_VALUE
;
800 PortConfig
->DmaPort
= SP_UNINITIALIZED_VALUE
;
801 // PortConfig->DmaWidth =
802 // PortConfig->DmaSpeed =
803 // PortConfig->AlignmentMask =
804 PortConfig
->NumberOfAccessRanges
= HwInitializationData
->NumberOfAccessRanges
;
805 // PortConfig->NumberOfBuses =
807 for (i
= 0; i
< SCSI_MAXIMUM_BUSES
; i
++)
808 PortConfig
->InitiatorBusId
[i
] = 255;
810 // PortConfig->ScatterGather =
811 // PortConfig->Master =
812 // PortConfig->CachesData =
813 // PortConfig->AdapterScansDown =
814 PortConfig
->AtdiskPrimaryClaimed
= SystemConfig
->AtDiskPrimaryAddressClaimed
;
815 PortConfig
->AtdiskSecondaryClaimed
= SystemConfig
->AtDiskSecondaryAddressClaimed
;
816 // PortConfig->Dma32BitAddresses =
817 // PortConfig->DemandMode =
818 PortConfig
->MapBuffers
= HwInitializationData
->MapBuffers
;
819 PortConfig
->NeedPhysicalAddresses
= HwInitializationData
->NeedPhysicalAddresses
;
820 PortConfig
->TaggedQueuing
= HwInitializationData
->TaggedQueueing
;
821 PortConfig
->AutoRequestSense
= HwInitializationData
->AutoRequestSense
;
822 PortConfig
->MultipleRequestPerLu
= HwInitializationData
->MultipleRequestPerLu
;
823 PortConfig
->ReceiveEvent
= HwInitializationData
->ReceiveEvent
;
824 // PortConfig->RealModeInitialized =
825 // PortConfig->BufferAccessScsiPortControlled =
826 PortConfig
->MaximumNumberOfTargets
= SCSI_MAXIMUM_TARGETS
;
827 // PortConfig->MaximumNumberOfLogicalUnits = SCSI_MAXIMUM_LOGICAL_UNITS;
829 PortConfig
->SlotNumber
= SlotNumber
.u
.AsULONG
;
831 PortConfig
->AccessRanges
= (PACCESS_RANGE
)(PortConfig
+ 1);
833 /* Search for matching PCI device */
834 if ((HwInitializationData
->AdapterInterfaceType
== PCIBus
) &&
835 (HwInitializationData
->VendorIdLength
> 0) &&
836 (HwInitializationData
->VendorId
!= NULL
) &&
837 (HwInitializationData
->DeviceIdLength
> 0) &&
838 (HwInitializationData
->DeviceId
!= NULL
))
840 /* Get PCI device data */
841 DPRINT("VendorId '%.*s' DeviceId '%.*s'\n",
842 HwInitializationData
->VendorIdLength
,
843 HwInitializationData
->VendorId
,
844 HwInitializationData
->DeviceIdLength
,
845 HwInitializationData
->DeviceId
);
847 if (!SpiGetPciConfigData (HwInitializationData
,
852 Status
= STATUS_UNSUCCESSFUL
;
857 /* Note: HwFindAdapter is called once for each bus */
859 DPRINT("Calling HwFindAdapter() for Bus %lu\n", PortConfig
->SystemIoBusNumber
);
860 Result
= (HwInitializationData
->HwFindAdapter
)(&DeviceExtension
->MiniPortDeviceExtension
,
862 0, /* BusInformation */
863 "", /* ArgumentString */
866 DPRINT("HwFindAdapter() Result: %lu Again: %s\n",
867 Result
, (Again
) ? "True" : "False");
869 if (Result
== SP_RETURN_FOUND
)
871 DPRINT("ScsiPortInitialize(): Found HBA! (%x)\n", PortConfig
->BusInterruptVector
);
873 /* Register an interrupt handler for this device */
874 MappedIrq
= HalGetInterruptVector(PortConfig
->AdapterInterfaceType
,
875 PortConfig
->SystemIoBusNumber
,
876 PortConfig
->BusInterruptLevel
,
877 PortConfig
->BusInterruptVector
,
880 Status
= IoConnectInterrupt(&DeviceExtension
->Interrupt
,
883 &DeviceExtension
->SpinLock
,
887 PortConfig
->InterruptMode
,
891 if (!NT_SUCCESS(Status
))
893 DbgPrint("Could not connect interrupt %d\n",
894 PortConfig
->BusInterruptVector
);
898 if (!(HwInitializationData
->HwInitialize
)(&DeviceExtension
->MiniPortDeviceExtension
))
900 DbgPrint("HwInitialize() failed!");
901 Status
= STATUS_UNSUCCESSFUL
;
905 /* Initialize port capabilities */
906 DeviceExtension
->PortCapabilities
= ExAllocatePool(NonPagedPool
,
907 sizeof(IO_SCSI_CAPABILITIES
));
908 if (DeviceExtension
->PortCapabilities
== NULL
)
910 DbgPrint("Failed to allocate port capabilities!\n");
911 Status
= STATUS_INSUFFICIENT_RESOURCES
;
915 PortCapabilities
= DeviceExtension
->PortCapabilities
;
916 PortCapabilities
->Length
= sizeof(IO_SCSI_CAPABILITIES
);
917 PortCapabilities
->MaximumTransferLength
=
918 PortConfig
->MaximumTransferLength
;
919 PortCapabilities
->MaximumPhysicalPages
=
920 PortCapabilities
->MaximumTransferLength
/ PAGE_SIZE
;
921 PortCapabilities
->SupportedAsynchronousEvents
= 0; /* FIXME */
922 PortCapabilities
->AlignmentMask
=
923 PortConfig
->AlignmentMask
;
924 PortCapabilities
->TaggedQueuing
=
925 PortConfig
->TaggedQueuing
;
926 PortCapabilities
->AdapterScansDown
=
927 PortConfig
->AdapterScansDown
;
928 PortCapabilities
->AdapterUsesPio
= TRUE
; /* FIXME */
930 /* Scan the adapter for devices */
931 SpiScanAdapter (DeviceExtension
);
933 /* Build the registry device map */
934 SpiBuildDeviceMap (DeviceExtension
,
935 (PUNICODE_STRING
)Argument2
);
937 /* Create the dos device link */
938 swprintf(DosNameBuffer
,
940 SystemConfig
->ScsiPortCount
);
941 RtlInitUnicodeString(&DosDeviceName
,
943 IoCreateSymbolicLink(&DosDeviceName
,
946 /* Update the system configuration info */
947 if (PortConfig
->AtdiskPrimaryClaimed
== TRUE
)
948 SystemConfig
->AtDiskPrimaryAddressClaimed
= TRUE
;
949 if (PortConfig
->AtdiskSecondaryClaimed
== TRUE
)
950 SystemConfig
->AtDiskSecondaryAddressClaimed
= TRUE
;
952 SystemConfig
->ScsiPortCount
++;
953 PortDeviceObject
= NULL
;
958 DPRINT("HwFindAdapter() Result: %lu\n", Result
);
960 ExFreePool (PortConfig
);
961 IoDeleteDevice (PortDeviceObject
);
962 PortDeviceObject
= NULL
;
965 DPRINT("Bus: %lu MaxBus: %lu\n", BusNumber
, MaxBus
);
966 if (BusNumber
>= MaxBus
)
968 DPRINT("Scanned all buses!\n");
969 Status
= STATUS_SUCCESS
;
976 SlotNumber
.u
.AsULONG
= 0;
981 /* Clean up the mess */
982 if (PortDeviceObject
!= NULL
)
984 DPRINT("Delete device: %p\n", PortDeviceObject
);
986 DeviceExtension
= PortDeviceObject
->DeviceExtension
;
988 if (DeviceExtension
->PortCapabilities
!= NULL
)
990 IoDisconnectInterrupt (DeviceExtension
->Interrupt
);
991 ExFreePool (DeviceExtension
->PortCapabilities
);
994 if (DeviceExtension
->PortConfig
!= NULL
)
996 ExFreePool (DeviceExtension
->PortConfig
);
999 IoDeleteDevice (PortDeviceObject
);
1002 DPRINT("ScsiPortInitialize() done!\n");
1004 return (DeviceFound
== FALSE
) ? Status
: STATUS_SUCCESS
;
1012 ScsiPortIoMapTransfer(IN PVOID HwDeviceExtension
,
1013 IN PSCSI_REQUEST_BLOCK Srb
,
1014 IN ULONG LogicalAddress
,
1017 DPRINT1("ScsiPortIoMapTransfer()\n");
1026 ScsiPortLogError(IN PVOID HwDeviceExtension
,
1027 IN PSCSI_REQUEST_BLOCK Srb OPTIONAL
,
1034 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
1036 DPRINT1("ScsiPortLogError() called\n");
1038 DeviceExtension
= CONTAINING_RECORD(HwDeviceExtension
,
1039 SCSI_PORT_DEVICE_EXTENSION
,
1040 MiniPortDeviceExtension
);
1043 DPRINT("ScsiPortLogError() done\n");
1051 ScsiPortMoveMemory(OUT PVOID Destination
,
1055 RtlMoveMemory(Destination
,
1065 ScsiPortNotification(IN SCSI_NOTIFICATION_TYPE NotificationType
,
1066 IN PVOID HwDeviceExtension
,
1069 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
1072 DPRINT("ScsiPortNotification() called\n");
1074 DeviceExtension
= CONTAINING_RECORD(HwDeviceExtension
,
1075 SCSI_PORT_DEVICE_EXTENSION
,
1076 MiniPortDeviceExtension
);
1078 DPRINT("DeviceExtension %p\n", DeviceExtension
);
1080 va_start(ap
, HwDeviceExtension
);
1082 switch (NotificationType
)
1084 case RequestComplete
:
1086 PSCSI_REQUEST_BLOCK Srb
;
1088 Srb
= (PSCSI_REQUEST_BLOCK
) va_arg (ap
, PSCSI_REQUEST_BLOCK
);
1090 DPRINT("Notify: RequestComplete (Srb %p)\n", Srb
);
1091 DeviceExtension
->IrpFlags
|= IRP_FLAG_COMPLETE
;
1096 DPRINT("Notify: NextRequest\n");
1097 DeviceExtension
->IrpFlags
|= IRP_FLAG_NEXT
;
1106 PathId
= (UCHAR
) va_arg (ap
, int);
1107 TargetId
= (UCHAR
) va_arg (ap
, int);
1108 Lun
= (UCHAR
) va_arg (ap
, int);
1110 DPRINT1 ("Notify: NextLuRequest(PathId %u TargetId %u Lun %u)\n",
1111 PathId
, TargetId
, Lun
);
1112 /* FIXME: Implement it! */
1114 DeviceExtension
->IrpFlags
|= IRP_FLAG_NEXT
;
1115 // DeviceExtension->IrpFlags |= IRP_FLAG_NEXT_LU;
1118 DeviceExtension
->IrpFlags
|= IRP_FLAG_NEXT
;
1123 DPRINT1("Notify: ResetDetected\n");
1128 DPRINT1 ("Unsupported notification %lu\n", NotificationType
);
1140 ScsiPortSetBusDataByOffset(IN PVOID DeviceExtension
,
1141 IN ULONG BusDataType
,
1142 IN ULONG SystemIoBusNumber
,
1143 IN ULONG SlotNumber
,
1148 DPRINT("ScsiPortSetBusDataByOffset()\n");
1149 return(HalSetBusDataByOffset(BusDataType
,
1162 ScsiPortValidateRange(IN PVOID HwDeviceExtension
,
1163 IN INTERFACE_TYPE BusType
,
1164 IN ULONG SystemIoBusNumber
,
1165 IN SCSI_PHYSICAL_ADDRESS IoAddress
,
1166 IN ULONG NumberOfBytes
,
1167 IN BOOLEAN InIoSpace
)
1169 DPRINT("ScsiPortValidateRange()\n");
1174 /* INTERNAL FUNCTIONS ********************************************************/
1178 SpiGetPciConfigData (IN
struct _HW_INITIALIZATION_DATA
*HwInitializationData
,
1179 IN OUT PPORT_CONFIGURATION_INFORMATION PortConfig
,
1181 IN OUT PPCI_SLOT_NUMBER NextSlotNumber
)
1183 PCI_COMMON_CONFIG PciConfig
;
1184 PCI_SLOT_NUMBER SlotNumber
;
1187 ULONG FunctionNumber
;
1188 CHAR VendorIdString
[8];
1189 CHAR DeviceIdString
[8];
1193 DPRINT ("SpiGetPciConfiguration() called\n");
1195 if (NextSlotNumber
->u
.bits
.FunctionNumber
>= PCI_MAX_FUNCTION
)
1197 NextSlotNumber
->u
.bits
.FunctionNumber
= 0;
1198 NextSlotNumber
->u
.bits
.DeviceNumber
++;
1201 if (NextSlotNumber
->u
.bits
.DeviceNumber
>= PCI_MAX_DEVICES
)
1203 NextSlotNumber
->u
.bits
.DeviceNumber
= 0;
1207 for (DeviceNumber
= NextSlotNumber
->u
.bits
.DeviceNumber
; DeviceNumber
< PCI_MAX_DEVICES
; DeviceNumber
++)
1209 SlotNumber
.u
.bits
.DeviceNumber
= DeviceNumber
;
1211 for (FunctionNumber
= NextSlotNumber
->u
.bits
.FunctionNumber
; FunctionNumber
< PCI_MAX_FUNCTION
; FunctionNumber
++)
1213 SlotNumber
.u
.bits
.FunctionNumber
= FunctionNumber
;
1215 DataSize
= HalGetBusData (PCIConfiguration
,
1217 SlotNumber
.u
.AsULONG
,
1219 PCI_COMMON_HDR_LENGTH
);
1220 if (DataSize
!= PCI_COMMON_HDR_LENGTH
)
1222 if (FunctionNumber
== 0)
1232 sprintf (VendorIdString
, "%04hx", PciConfig
.VendorID
);
1233 sprintf (DeviceIdString
, "%04hx", PciConfig
.DeviceID
);
1235 if (!_strnicmp(VendorIdString
, HwInitializationData
->VendorId
, HwInitializationData
->VendorIdLength
) &&
1236 !_strnicmp(DeviceIdString
, HwInitializationData
->DeviceId
, HwInitializationData
->DeviceIdLength
))
1238 DPRINT ("Found device 0x%04hx 0x%04hx at %1lu %2lu %1lu\n",
1242 SlotNumber
.u
.bits
.DeviceNumber
,
1243 SlotNumber
.u
.bits
.FunctionNumber
);
1245 PortConfig
->BusInterruptLevel
=
1246 PortConfig
->BusInterruptVector
= PciConfig
.u
.type0
.InterruptLine
;
1247 PortConfig
->SlotNumber
= SlotNumber
.u
.AsULONG
;
1249 /* Initialize access ranges */
1250 if (PortConfig
->NumberOfAccessRanges
> 0)
1252 if (PortConfig
->NumberOfAccessRanges
> PCI_TYPE0_ADDRESSES
)
1253 PortConfig
->NumberOfAccessRanges
= PCI_TYPE0_ADDRESSES
;
1255 for (i
= 0; i
< PortConfig
->NumberOfAccessRanges
; i
++)
1257 PortConfig
->AccessRanges
[i
].RangeStart
.QuadPart
=
1258 PciConfig
.u
.type0
.BaseAddresses
[i
] & PCI_ADDRESS_IO_ADDRESS_MASK
;
1259 if (PortConfig
->AccessRanges
[i
].RangeStart
.QuadPart
!= 0)
1261 RangeLength
= (ULONG
)-1;
1262 HalSetBusDataByOffset (PCIConfiguration
,
1264 SlotNumber
.u
.AsULONG
,
1265 (PVOID
)&RangeLength
,
1266 0x10 + (i
* sizeof(ULONG
)),
1269 HalGetBusDataByOffset (PCIConfiguration
,
1271 SlotNumber
.u
.AsULONG
,
1272 (PVOID
)&RangeLength
,
1273 0x10 + (i
* sizeof(ULONG
)),
1276 HalSetBusDataByOffset (PCIConfiguration
,
1278 SlotNumber
.u
.AsULONG
,
1279 (PVOID
)&PciConfig
.u
.type0
.BaseAddresses
[i
],
1280 0x10 + (i
* sizeof(ULONG
)),
1282 if (RangeLength
!= 0)
1284 PortConfig
->AccessRanges
[0].RangeLength
=
1285 -(RangeLength
& PCI_ADDRESS_IO_ADDRESS_MASK
);
1286 PortConfig
->AccessRanges
[i
].RangeInMemory
=
1287 !(PciConfig
.u
.type0
.BaseAddresses
[i
] & PCI_ADDRESS_IO_SPACE
);
1289 DPRINT("RangeStart 0x%lX RangeLength 0x%lX RangeInMemory %s\n",
1290 PciConfig
.u
.type0
.BaseAddresses
[i
] & PCI_ADDRESS_IO_ADDRESS_MASK
,
1291 -(RangeLength
& PCI_ADDRESS_IO_ADDRESS_MASK
),
1292 (PciConfig
.u
.type0
.BaseAddresses
[i
] & PCI_ADDRESS_IO_SPACE
)?"FALSE":"TRUE");
1298 NextSlotNumber
->u
.bits
.DeviceNumber
= DeviceNumber
;
1299 NextSlotNumber
->u
.bits
.FunctionNumber
= FunctionNumber
+ 1;
1305 if (FunctionNumber
== 0 && !(PciConfig
.HeaderType
& PCI_MULTIFUNCTION
))
1310 NextSlotNumber
->u
.bits
.FunctionNumber
= 0;
1313 DPRINT ("No device found\n");
1320 /**********************************************************************
1322 * ScsiPortCreateClose
1325 * Answer requests for Create/Close calls: a null operation.
1332 * Pointer to a device object.
1335 * Pointer to an IRP.
1341 static NTSTATUS STDCALL
1342 ScsiPortCreateClose(IN PDEVICE_OBJECT DeviceObject
,
1345 DPRINT("ScsiPortCreateClose()\n");
1347 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1348 Irp
->IoStatus
.Information
= FILE_OPENED
;
1350 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1352 return(STATUS_SUCCESS
);
1356 /**********************************************************************
1358 * ScsiPortDispatchScsi
1361 * Answer requests for SCSI calls
1367 * Standard dispatch arguments
1373 static NTSTATUS STDCALL
1374 ScsiPortDispatchScsi(IN PDEVICE_OBJECT DeviceObject
,
1377 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
1378 PSCSI_PORT_LUN_EXTENSION LunExtension
;
1379 PIO_STACK_LOCATION Stack
;
1380 PSCSI_REQUEST_BLOCK Srb
;
1381 NTSTATUS Status
= STATUS_SUCCESS
;
1384 DPRINT("ScsiPortDispatchScsi(DeviceObject %p Irp %p)\n",
1387 DeviceExtension
= DeviceObject
->DeviceExtension
;
1388 Stack
= IoGetCurrentIrpStackLocation(Irp
);
1390 Srb
= Stack
->Parameters
.Scsi
.Srb
;
1393 Status
= STATUS_UNSUCCESSFUL
;
1395 Irp
->IoStatus
.Status
= Status
;
1396 Irp
->IoStatus
.Information
= 0;
1398 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1403 DPRINT("Srb: %p\n", Srb
);
1404 DPRINT("Srb->Function: %lu\n", Srb
->Function
);
1405 DPRINT("PathId: %lu TargetId: %lu Lun: %lu\n", Srb
->PathId
, Srb
->TargetId
, Srb
->Lun
);
1407 LunExtension
= SpiGetLunExtension(DeviceExtension
,
1411 if (LunExtension
== NULL
)
1413 Status
= STATUS_NO_SUCH_DEVICE
;
1415 Srb
->SrbStatus
= SRB_STATUS_NO_DEVICE
;
1416 Irp
->IoStatus
.Status
= Status
;
1417 Irp
->IoStatus
.Information
= 0;
1419 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1424 switch (Srb
->Function
)
1426 case SRB_FUNCTION_EXECUTE_SCSI
:
1427 case SRB_FUNCTION_IO_CONTROL
:
1428 #ifdef USE_DEVICE_QUEUES
1429 if (Srb
->SrbFlags
& SRB_FLAGS_BYPASS_FROZEN_QUEUE
)
1431 IoMarkIrpPending(Irp
);
1432 IoStartPacket (DeviceObject
, Irp
, NULL
, NULL
);
1438 KeRaiseIrql (DISPATCH_LEVEL
,
1441 if (!KeInsertByKeyDeviceQueue (&LunExtension
->DeviceQueue
,
1442 &Irp
->Tail
.Overlay
.DeviceQueueEntry
,
1445 Srb
->SrbStatus
= SRB_STATUS_SUCCESS
;
1446 IoMarkIrpPending(Irp
);
1447 IoStartPacket (DeviceObject
, Irp
, NULL
, NULL
);
1450 KeLowerIrql (oldIrql
);
1453 IoMarkIrpPending(Irp
);
1454 IoStartPacket (DeviceObject
, Irp
, NULL
, NULL
);
1456 return(STATUS_PENDING
);
1458 case SRB_FUNCTION_SHUTDOWN
:
1459 case SRB_FUNCTION_FLUSH
:
1460 if (DeviceExtension
->PortConfig
->CachesData
== TRUE
)
1462 IoMarkIrpPending(Irp
);
1463 IoStartPacket(DeviceObject
, Irp
, NULL
, NULL
);
1464 return(STATUS_PENDING
);
1468 case SRB_FUNCTION_CLAIM_DEVICE
:
1469 DPRINT (" SRB_FUNCTION_CLAIM_DEVICE\n");
1471 /* Reference device object and keep the device object */
1472 ObReferenceObject(DeviceObject
);
1473 LunExtension
->DeviceObject
= DeviceObject
;
1474 LunExtension
->DeviceClaimed
= TRUE
;
1475 Srb
->DataBuffer
= DeviceObject
;
1478 case SRB_FUNCTION_RELEASE_DEVICE
:
1479 DPRINT (" SRB_FUNCTION_RELEASE_DEVICE\n");
1480 DPRINT ("PathId: %lu TargetId: %lu Lun: %lu\n",
1481 Srb
->PathId
, Srb
->TargetId
, Srb
->Lun
);
1483 /* Dereference device object and clear the device object */
1484 ObDereferenceObject(LunExtension
->DeviceObject
);
1485 LunExtension
->DeviceObject
= NULL
;
1486 LunExtension
->DeviceClaimed
= FALSE
;
1490 DPRINT1("SRB function not implemented (Function %lu)\n", Srb
->Function
);
1491 Status
= STATUS_NOT_IMPLEMENTED
;
1495 Irp
->IoStatus
.Status
= Status
;
1496 Irp
->IoStatus
.Information
= DataSize
;
1498 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1504 /**********************************************************************
1506 * ScsiPortDeviceControl
1509 * Answer requests for device control calls
1515 * Standard dispatch arguments
1521 static NTSTATUS STDCALL
1522 ScsiPortDeviceControl(IN PDEVICE_OBJECT DeviceObject
,
1525 PIO_STACK_LOCATION Stack
;
1526 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
1528 DPRINT("ScsiPortDeviceControl()\n");
1530 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1531 Irp
->IoStatus
.Information
= 0;
1534 Stack
= IoGetCurrentIrpStackLocation(Irp
);
1535 DeviceExtension
= DeviceObject
->DeviceExtension
;
1537 switch (Stack
->Parameters
.DeviceIoControl
.IoControlCode
)
1539 case IOCTL_SCSI_GET_DUMP_POINTERS
:
1541 PDUMP_POINTERS DumpPointers
;
1542 DPRINT(" IOCTL_SCSI_GET_DUMP_POINTERS\n");
1543 DumpPointers
= (PDUMP_POINTERS
)Irp
->AssociatedIrp
.SystemBuffer
;
1544 DumpPointers
->DeviceObject
= DeviceObject
;
1546 Irp
->IoStatus
.Information
= sizeof(DUMP_POINTERS
);
1550 case IOCTL_SCSI_GET_CAPABILITIES
:
1552 DPRINT(" IOCTL_SCSI_GET_CAPABILITIES\n");
1554 *((PIO_SCSI_CAPABILITIES
*)Irp
->AssociatedIrp
.SystemBuffer
) =
1555 DeviceExtension
->PortCapabilities
;
1557 Irp
->IoStatus
.Information
= sizeof(PIO_SCSI_CAPABILITIES
);
1561 case IOCTL_SCSI_GET_INQUIRY_DATA
:
1563 DPRINT(" IOCTL_SCSI_GET_INQUIRY_DATA\n");
1565 /* Copy inquiry data to the port device extension */
1566 Irp
->IoStatus
.Information
=
1567 SpiGetInquiryData(DeviceExtension
,
1568 Irp
->AssociatedIrp
.SystemBuffer
);
1569 DPRINT("Inquiry data size: %lu\n", Irp
->IoStatus
.Information
);
1574 DPRINT1(" unknown ioctl code: 0x%lX\n",
1575 Stack
->Parameters
.DeviceIoControl
.IoControlCode
);
1579 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1581 return(STATUS_SUCCESS
);
1586 ScsiPortStartIo(IN PDEVICE_OBJECT DeviceObject
,
1589 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
1590 PSCSI_PORT_LUN_EXTENSION LunExtension
;
1591 PIO_STACK_LOCATION IrpStack
;
1592 PSCSI_REQUEST_BLOCK Srb
;
1595 DPRINT("ScsiPortStartIo() called!\n");
1597 DeviceExtension
= DeviceObject
->DeviceExtension
;
1598 IrpStack
= IoGetCurrentIrpStackLocation(Irp
);
1600 DPRINT("DeviceExtension %p\n", DeviceExtension
);
1602 oldIrql
= KeGetCurrentIrql();
1604 if (IrpStack
->MajorFunction
!= IRP_MJ_SCSI
)
1606 DPRINT("No IRP_MJ_SCSI!\n");
1607 Irp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
1608 Irp
->IoStatus
.Information
= 0;
1609 IoCompleteRequest (Irp
,
1611 if (oldIrql
< DISPATCH_LEVEL
)
1613 KeRaiseIrql (DISPATCH_LEVEL
,
1615 IoStartNextPacket (DeviceObject
,
1617 KeLowerIrql (oldIrql
);
1621 IoStartNextPacket (DeviceObject
,
1627 Srb
= IrpStack
->Parameters
.Scsi
.Srb
;
1629 LunExtension
= SpiGetLunExtension(DeviceExtension
,
1633 if (LunExtension
== NULL
)
1635 DPRINT("Can't get LunExtension!\n");
1636 Irp
->IoStatus
.Status
= STATUS_NO_SUCH_DEVICE
;
1637 Irp
->IoStatus
.Information
= 0;
1638 IoCompleteRequest (Irp
,
1640 if (oldIrql
< DISPATCH_LEVEL
)
1642 KeRaiseIrql (DISPATCH_LEVEL
,
1644 IoStartNextPacket (DeviceObject
,
1646 KeLowerIrql (oldIrql
);
1650 IoStartNextPacket (DeviceObject
,
1656 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1657 Irp
->IoStatus
.Information
= Srb
->DataTransferLength
;
1659 DeviceExtension
->CurrentIrp
= Irp
;
1661 if (!KeSynchronizeExecution(DeviceExtension
->Interrupt
,
1662 ScsiPortStartPacket
,
1665 DPRINT("Synchronization failed!\n");
1667 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
1668 Irp
->IoStatus
.Information
= 0;
1669 IoCompleteRequest(Irp
,
1671 if (oldIrql
< DISPATCH_LEVEL
)
1673 KeRaiseIrql (DISPATCH_LEVEL
,
1675 IoStartNextPacket (DeviceObject
,
1677 KeLowerIrql (oldIrql
);
1681 IoStartNextPacket (DeviceObject
,
1686 KeAcquireSpinLock(&DeviceExtension
->IrpLock
, &oldIrql
);
1687 if (DeviceExtension
->IrpFlags
& IRP_FLAG_COMPLETE
)
1689 DeviceExtension
->IrpFlags
&= ~IRP_FLAG_COMPLETE
;
1690 IoCompleteRequest(Irp
,
1694 if (DeviceExtension
->IrpFlags
& IRP_FLAG_NEXT
)
1696 DeviceExtension
->IrpFlags
&= ~IRP_FLAG_NEXT
;
1697 KeReleaseSpinLockFromDpcLevel(&DeviceExtension
->IrpLock
);
1698 IoStartNextPacket(DeviceObject
,
1700 KeLowerIrql(oldIrql
);
1704 KeReleaseSpinLock(&DeviceExtension
->IrpLock
, oldIrql
);
1707 DPRINT("ScsiPortStartIo() done\n");
1711 static BOOLEAN STDCALL
1712 ScsiPortStartPacket(IN OUT PVOID Context
)
1714 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
1715 PIO_STACK_LOCATION IrpStack
;
1716 PSCSI_REQUEST_BLOCK Srb
;
1718 DPRINT("ScsiPortStartPacket() called\n");
1720 DeviceExtension
= (PSCSI_PORT_DEVICE_EXTENSION
)Context
;
1722 IrpStack
= IoGetCurrentIrpStackLocation(DeviceExtension
->CurrentIrp
);
1723 Srb
= IrpStack
->Parameters
.Scsi
.Srb
;
1725 /* Allocte SRB extension */
1726 if (DeviceExtension
->SrbExtensionSize
!= 0)
1728 Srb
->SrbExtension
= DeviceExtension
->VirtualAddress
;
1731 return(DeviceExtension
->HwStartIo(&DeviceExtension
->MiniPortDeviceExtension
,
1736 static PSCSI_PORT_LUN_EXTENSION
1737 SpiAllocateLunExtension (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
1742 PSCSI_PORT_LUN_EXTENSION LunExtension
;
1743 ULONG LunExtensionSize
;
1745 DPRINT("SpiAllocateLunExtension (%p %u %u %u)\n",
1746 DeviceExtension
, PathId
, TargetId
, Lun
);
1749 sizeof(SCSI_PORT_LUN_EXTENSION
) + DeviceExtension
->LunExtensionSize
;
1750 DPRINT("LunExtensionSize %lu\n", LunExtensionSize
);
1752 LunExtension
= ExAllocatePool(NonPagedPool
,
1754 if (LunExtension
== NULL
)
1759 RtlZeroMemory(LunExtension
,
1762 InsertTailList(&DeviceExtension
->LunExtensionListHead
,
1763 &LunExtension
->List
);
1765 LunExtension
->PathId
= PathId
;
1766 LunExtension
->TargetId
= TargetId
;
1767 LunExtension
->Lun
= Lun
;
1769 KeInitializeDeviceQueue (&LunExtension
->DeviceQueue
);
1771 return LunExtension
;
1776 SpiRemoveLunExtension (IN PSCSI_PORT_LUN_EXTENSION LunExtension
)
1778 DPRINT("SpiRemoveLunExtension(%p) called\n",
1781 if (LunExtension
== NULL
)
1784 RemoveEntryList (&LunExtension
->List
);
1787 /* Release LUN extersion data */
1790 ExFreePool (LunExtension
);
1796 static PSCSI_PORT_LUN_EXTENSION
1797 SpiGetLunExtension (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
1802 PSCSI_PORT_LUN_EXTENSION LunExtension
;
1805 DPRINT("SpiGetLunExtension(%p %u %u %u) called\n",
1806 DeviceExtension
, PathId
, TargetId
, Lun
);
1808 if (IsListEmpty(&DeviceExtension
->LunExtensionListHead
))
1811 Entry
= DeviceExtension
->LunExtensionListHead
.Flink
;
1812 while (Entry
!= &DeviceExtension
->LunExtensionListHead
)
1814 LunExtension
= CONTAINING_RECORD(Entry
,
1815 SCSI_PORT_LUN_EXTENSION
,
1817 if (LunExtension
->PathId
== PathId
&&
1818 LunExtension
->TargetId
== TargetId
&&
1819 LunExtension
->Lun
== Lun
)
1821 return LunExtension
;
1824 Entry
= Entry
->Flink
;
1832 SpiSendInquiry (IN PDEVICE_OBJECT DeviceObject
,
1833 IN OUT PSCSI_REQUEST_BLOCK Srb
)
1835 IO_STATUS_BLOCK IoStatusBlock
;
1836 PIO_STACK_LOCATION IrpStack
;
1841 DPRINT ("SpiSendInquiry() called\n");
1843 Event
= ExAllocatePool (NonPagedPool
,
1846 return STATUS_INSUFFICIENT_RESOURCES
;
1848 KeInitializeEvent (Event
,
1852 Irp
= IoBuildDeviceIoControlRequest (IOCTL_SCSI_EXECUTE_OUT
,
1857 Srb
->DataTransferLength
,
1863 DPRINT("IoBuildDeviceIoControlRequest() failed\n");
1865 return STATUS_INSUFFICIENT_RESOURCES
;
1868 /* Attach Srb to the Irp */
1869 IrpStack
= IoGetNextIrpStackLocation (Irp
);
1870 IrpStack
->Parameters
.Scsi
.Srb
= Srb
;
1871 Srb
->OriginalRequest
= Irp
;
1873 /* Call the driver */
1874 Status
= IoCallDriver (DeviceObject
,
1876 if (Status
== STATUS_PENDING
)
1878 KeWaitForSingleObject (Event
,
1883 Status
= IoStatusBlock
.Status
;
1893 SpiScanAdapter (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
)
1895 PSCSI_PORT_LUN_EXTENSION LunExtension
;
1896 SCSI_REQUEST_BLOCK Srb
;
1903 DPRINT ("SpiScanAdapter() called\n");
1906 sizeof(SCSI_REQUEST_BLOCK
));
1907 Srb
.SrbFlags
= SRB_FLAGS_DATA_IN
;
1908 Srb
.DataBuffer
= ExAllocatePool(NonPagedPool
, 256);
1909 Srb
.Function
= SRB_FUNCTION_EXECUTE_SCSI
;
1910 Srb
.DataTransferLength
= 255; //256;
1913 Cdb
= (PCDB
) &Srb
.Cdb
;
1915 Cdb
->CDB6INQUIRY
.OperationCode
= SCSIOP_INQUIRY
;
1916 Cdb
->CDB6INQUIRY
.AllocationLength
= 255;
1918 for (Bus
= 0; Bus
< DeviceExtension
->PortConfig
->NumberOfBuses
; Bus
++)
1922 for (Target
= 0; Target
< DeviceExtension
->PortConfig
->MaximumNumberOfTargets
; Target
++)
1924 Srb
.TargetId
= Target
;
1926 for (Lun
= 0; Lun
< SCSI_MAXIMUM_LOGICAL_UNITS
; Lun
++)
1929 Srb
.SrbStatus
= SRB_STATUS_SUCCESS
;
1931 Cdb
->CDB6INQUIRY
.LogicalUnitNumber
= Lun
;
1933 LunExtension
= SpiAllocateLunExtension (DeviceExtension
,
1937 if (LunExtension
== NULL
)
1939 DPRINT("Failed to allocate the LUN extension!\n");
1940 ExFreePool(Srb
.DataBuffer
);
1944 Status
= SpiSendInquiry (DeviceExtension
->DeviceObject
,
1946 DPRINT ("Status %lx Srb.SrbStatus %x\n", Status
, Srb
.SrbStatus
);
1948 if (NT_SUCCESS(Status
) &&
1949 (Srb
.SrbStatus
== SRB_STATUS_SUCCESS
||
1950 Srb
.SrbStatus
== SRB_STATUS_DATA_OVERRUN
) &&
1951 ((PINQUIRYDATA
)Srb
.DataBuffer
)->DeviceTypeQualifier
== 0)
1953 /* Copy inquiry data */
1954 RtlCopyMemory (&LunExtension
->InquiryData
,
1956 sizeof(INQUIRYDATA
));
1960 SpiRemoveLunExtension (LunExtension
);
1966 ExFreePool(Srb
.DataBuffer
);
1968 DPRINT ("SpiScanAdapter() done\n");
1973 SpiGetInquiryData(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
1974 OUT PSCSI_ADAPTER_BUS_INFO AdapterBusInfo
)
1976 PSCSI_PORT_LUN_EXTENSION LunExtension
;
1977 PSCSI_INQUIRY_DATA UnitInfo
, PrevUnit
;
1983 DPRINT("SpiGetInquiryData() called\n");
1985 /* Copy inquiry data to the port device extension */
1986 AdapterBusInfo
->NumberOfBuses
= DeviceExtension
->PortConfig
->NumberOfBuses
;
1988 UnitInfo
= (PSCSI_INQUIRY_DATA
)
1989 ((PUCHAR
)AdapterBusInfo
+ sizeof(SCSI_ADAPTER_BUS_INFO
) +
1990 (sizeof(SCSI_BUS_DATA
) * (AdapterBusInfo
->NumberOfBuses
- 1)));
1992 for (Bus
= 0; Bus
< AdapterBusInfo
->NumberOfBuses
; Bus
++)
1994 AdapterBusInfo
->BusData
[Bus
].InitiatorBusId
=
1995 DeviceExtension
->PortConfig
->InitiatorBusId
[Bus
];
1996 AdapterBusInfo
->BusData
[Bus
].InquiryDataOffset
=
1997 (ULONG
)((PUCHAR
)UnitInfo
- (PUCHAR
)AdapterBusInfo
);
2002 for (Target
= 0; Target
< DeviceExtension
->PortConfig
->MaximumNumberOfTargets
; Target
++)
2004 for (Lun
= 0; Lun
< SCSI_MAXIMUM_LOGICAL_UNITS
; Lun
++)
2006 LunExtension
= SpiGetLunExtension(DeviceExtension
,
2010 if (LunExtension
!= NULL
)
2012 DPRINT("(Bus %lu Target %lu Lun %lu)\n",
2015 UnitInfo
->PathId
= Bus
;
2016 UnitInfo
->TargetId
= Target
;
2017 UnitInfo
->Lun
= Lun
;
2018 UnitInfo
->InquiryDataLength
= INQUIRYDATABUFFERSIZE
;
2019 RtlCopyMemory (&UnitInfo
->InquiryData
,
2020 &LunExtension
->InquiryData
,
2021 INQUIRYDATABUFFERSIZE
);
2022 if (PrevUnit
!= NULL
)
2024 PrevUnit
->NextInquiryDataOffset
=
2025 (ULONG
)((ULONG_PTR
)UnitInfo
-(ULONG_PTR
)AdapterBusInfo
);
2027 PrevUnit
= UnitInfo
;
2028 UnitInfo
= (PSCSI_INQUIRY_DATA
)((PUCHAR
)UnitInfo
+ sizeof(SCSI_INQUIRY_DATA
)+INQUIRYDATABUFFERSIZE
-1);
2033 DPRINT("UnitCount: %lu\n", UnitCount
);
2034 AdapterBusInfo
->BusData
[Bus
].NumberOfLogicalUnits
= UnitCount
;
2037 AdapterBusInfo
->BusData
[Bus
].InquiryDataOffset
= 0;
2041 DPRINT("Data size: %lu\n", (ULONG
)UnitInfo
- (ULONG
)AdapterBusInfo
);
2043 return (ULONG
)((PUCHAR
)UnitInfo
-(PUCHAR
)AdapterBusInfo
);
2047 static BOOLEAN STDCALL
2048 ScsiPortIsr(IN PKINTERRUPT Interrupt
,
2049 IN PVOID ServiceContext
)
2051 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
2054 DPRINT("ScsiPortIsr() called!\n");
2056 DeviceExtension
= (PSCSI_PORT_DEVICE_EXTENSION
)ServiceContext
;
2058 Result
= DeviceExtension
->HwInterrupt(&DeviceExtension
->MiniPortDeviceExtension
);
2059 if (Result
== FALSE
)
2064 if (DeviceExtension
->IrpFlags
)
2066 IoRequestDpc(DeviceExtension
->DeviceObject
,
2067 DeviceExtension
->CurrentIrp
,
2075 // ScsiPortDpcForIsr
2082 // IN PDEVICE_OBJECT DpcDeviceObject
2084 // IN PVOID DpcContext
2087 ScsiPortDpcForIsr(IN PKDPC Dpc
,
2088 IN PDEVICE_OBJECT DpcDeviceObject
,
2090 IN PVOID DpcContext
)
2092 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
2093 PIO_STACK_LOCATION IrpStack
;
2094 PSCSI_REQUEST_BLOCK Srb
;
2096 DPRINT("ScsiPortDpcForIsr(Dpc %p DpcDeviceObject %p DpcIrp %p DpcContext %p)\n",
2097 Dpc
, DpcDeviceObject
, DpcIrp
, DpcContext
);
2099 DeviceExtension
= (PSCSI_PORT_DEVICE_EXTENSION
)DpcContext
;
2101 KeAcquireSpinLockAtDpcLevel(&DeviceExtension
->IrpLock
);
2102 if (DeviceExtension
->IrpFlags
)
2104 IrpStack
= IoGetCurrentIrpStackLocation(DeviceExtension
->CurrentIrp
);
2105 Srb
= IrpStack
->Parameters
.Scsi
.Srb
;
2107 if (DeviceExtension
->OriginalSrb
!= NULL
)
2109 DPRINT("Got sense data!\n");
2111 DPRINT("Valid: %x\n", DeviceExtension
->InternalSenseData
.Valid
);
2112 DPRINT("ErrorCode: %x\n", DeviceExtension
->InternalSenseData
.ErrorCode
);
2113 DPRINT("SenseKey: %x\n", DeviceExtension
->InternalSenseData
.SenseKey
);
2114 DPRINT("SenseCode: %x\n", DeviceExtension
->InternalSenseData
.AdditionalSenseCode
);
2116 /* Copy sense data */
2117 if (DeviceExtension
->OriginalSrb
->SenseInfoBufferLength
!= 0)
2119 RtlCopyMemory(DeviceExtension
->OriginalSrb
->SenseInfoBuffer
,
2120 &DeviceExtension
->InternalSenseData
,
2121 sizeof(SENSE_DATA
));
2122 DeviceExtension
->OriginalSrb
->SrbStatus
|= SRB_STATUS_AUTOSENSE_VALID
;
2125 /* Clear current sense data */
2126 RtlZeroMemory(&DeviceExtension
->InternalSenseData
, sizeof(SENSE_DATA
));
2128 IrpStack
->Parameters
.Scsi
.Srb
= DeviceExtension
->OriginalSrb
;
2129 ScsiPortFreeSenseRequestSrb (DeviceExtension
);
2131 else if ((SRB_STATUS(Srb
->SrbStatus
) != SRB_STATUS_SUCCESS
) &&
2132 (Srb
->ScsiStatus
== SCSISTAT_CHECK_CONDITION
))
2134 DPRINT("SCSIOP_REQUEST_SENSE required!\n");
2136 DeviceExtension
->OriginalSrb
= Srb
;
2137 IrpStack
->Parameters
.Scsi
.Srb
= ScsiPortInitSenseRequestSrb(DeviceExtension
,
2139 KeReleaseSpinLockFromDpcLevel(&DeviceExtension
->IrpLock
);
2140 if (!KeSynchronizeExecution(DeviceExtension
->Interrupt
,
2141 ScsiPortStartPacket
,
2144 DPRINT1("Synchronization failed!\n");
2146 DpcIrp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
2147 DpcIrp
->IoStatus
.Information
= 0;
2148 IoCompleteRequest(DpcIrp
,
2150 IoStartNextPacket(DpcDeviceObject
,
2157 DeviceExtension
->CurrentIrp
= NULL
;
2159 // DpcIrp->IoStatus.Information = 0;
2160 // DpcIrp->IoStatus.Status = STATUS_SUCCESS;
2162 if (DeviceExtension
->IrpFlags
& IRP_FLAG_COMPLETE
)
2164 DeviceExtension
->IrpFlags
&= ~IRP_FLAG_COMPLETE
;
2165 IoCompleteRequest(DpcIrp
, IO_NO_INCREMENT
);
2168 if (DeviceExtension
->IrpFlags
& IRP_FLAG_NEXT
)
2170 DeviceExtension
->IrpFlags
&= ~IRP_FLAG_NEXT
;
2171 KeReleaseSpinLockFromDpcLevel(&DeviceExtension
->IrpLock
);
2172 IoStartNextPacket(DpcDeviceObject
, FALSE
);
2176 KeReleaseSpinLockFromDpcLevel(&DeviceExtension
->IrpLock
);
2181 KeReleaseSpinLockFromDpcLevel(&DeviceExtension
->IrpLock
);
2184 DPRINT("ScsiPortDpcForIsr() done\n");
2190 // This function handles timeouts and other time delayed processing
2195 // IN PDEVICE_OBJECT DeviceObject Device object registered with timer
2196 // IN PVOID Context the Controller extension for the
2197 // controller the device is on
2200 ScsiPortIoTimer(PDEVICE_OBJECT DeviceObject
,
2203 DPRINT1("ScsiPortIoTimer()\n");
2207 static PSCSI_REQUEST_BLOCK
2208 ScsiPortInitSenseRequestSrb(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
2209 PSCSI_REQUEST_BLOCK OriginalSrb
)
2211 PSCSI_REQUEST_BLOCK Srb
;
2214 Srb
= &DeviceExtension
->InternalSrb
;
2217 sizeof(SCSI_REQUEST_BLOCK
));
2219 Srb
->PathId
= OriginalSrb
->PathId
;
2220 Srb
->TargetId
= OriginalSrb
->TargetId
;
2221 Srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
2222 Srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
2223 Srb
->SrbFlags
= SRB_FLAGS_DATA_IN
| SRB_FLAGS_DISABLE_SYNCH_TRANSFER
;
2225 Srb
->TimeOutValue
= 4;
2228 Srb
->DataBuffer
= &DeviceExtension
->InternalSenseData
;
2229 Srb
->DataTransferLength
= sizeof(SENSE_DATA
);
2231 Cdb
= (PCDB
)Srb
->Cdb
;
2232 Cdb
->CDB6INQUIRY
.OperationCode
= SCSIOP_REQUEST_SENSE
;
2233 Cdb
->CDB6INQUIRY
.AllocationLength
= sizeof(SENSE_DATA
);
2240 ScsiPortFreeSenseRequestSrb(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
)
2242 DeviceExtension
->OriginalSrb
= NULL
;
2246 /**********************************************************************
2251 * Builds the registry device map of all device which are attached
2252 * to the given SCSI HBA port. The device map is located at:
2253 * \Registry\Machine\DeviceMap\Scsi
2263 * Name of registry driver service key.
2270 SpiBuildDeviceMap (PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
2271 PUNICODE_STRING RegistryPath
)
2273 PSCSI_PORT_LUN_EXTENSION LunExtension
;
2274 OBJECT_ATTRIBUTES ObjectAttributes
;
2275 UNICODE_STRING KeyName
;
2276 UNICODE_STRING ValueName
;
2277 WCHAR NameBuffer
[64];
2280 HANDLE ScsiPortKey
= NULL
;
2281 HANDLE ScsiBusKey
= NULL
;
2282 HANDLE ScsiInitiatorKey
= NULL
;
2283 HANDLE ScsiTargetKey
= NULL
;
2284 HANDLE ScsiLunKey
= NULL
;
2287 ULONG CurrentTarget
;
2294 DPRINT("SpiBuildDeviceMap() called\n");
2296 if (DeviceExtension
== NULL
|| RegistryPath
== NULL
)
2298 DPRINT1("Invalid parameter\n");
2299 return(STATUS_INVALID_PARAMETER
);
2302 /* Open or create the 'Scsi' subkey */
2303 RtlRosInitUnicodeStringFromLiteral(&KeyName
,
2304 L
"\\Registry\\Machine\\Hardware\\DeviceMap\\Scsi");
2305 InitializeObjectAttributes(&ObjectAttributes
,
2307 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
,
2310 Status
= ZwCreateKey(&ScsiKey
,
2315 REG_OPTION_VOLATILE
,
2317 if (!NT_SUCCESS(Status
))
2319 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status
);
2323 /* Create new 'Scsi Port X' subkey */
2324 DPRINT("Scsi Port %lu\n",
2325 DeviceExtension
->PortNumber
);
2327 swprintf(NameBuffer
,
2329 DeviceExtension
->PortNumber
);
2330 RtlInitUnicodeString(&KeyName
,
2332 InitializeObjectAttributes(&ObjectAttributes
,
2337 Status
= ZwCreateKey(&ScsiPortKey
,
2342 REG_OPTION_VOLATILE
,
2345 if (!NT_SUCCESS(Status
))
2347 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status
);
2352 * Create port-specific values
2355 /* Set 'DMA Enabled' (REG_DWORD) value */
2356 UlongData
= (ULONG
)!DeviceExtension
->PortCapabilities
->AdapterUsesPio
;
2357 DPRINT(" DMA Enabled = %s\n", (UlongData
) ? "TRUE" : "FALSE");
2358 RtlInitUnicodeString(&ValueName
,
2360 Status
= ZwSetValueKey(ScsiPortKey
,
2366 if (!NT_SUCCESS(Status
))
2368 DPRINT("ZwSetValueKey('DMA Enabled') failed (Status %lx)\n", Status
);
2369 ZwClose(ScsiPortKey
);
2373 /* Set 'Driver' (REG_SZ) value */
2374 DriverName
= wcsrchr(RegistryPath
->Buffer
, L
'\\') + 1;
2375 RtlInitUnicodeString(&ValueName
,
2377 Status
= ZwSetValueKey(ScsiPortKey
,
2382 (wcslen(DriverName
) + 1) * sizeof(WCHAR
));
2383 if (!NT_SUCCESS(Status
))
2385 DPRINT("ZwSetValueKey('Driver') failed (Status %lx)\n", Status
);
2386 ZwClose(ScsiPortKey
);
2390 /* Set 'Interrupt' (REG_DWORD) value (NT4 only) */
2391 UlongData
= (ULONG
)DeviceExtension
->PortConfig
->BusInterruptLevel
;
2392 DPRINT(" Interrupt = %lu\n", UlongData
);
2393 RtlInitUnicodeString(&ValueName
,
2395 Status
= ZwSetValueKey(ScsiPortKey
,
2401 if (!NT_SUCCESS(Status
))
2403 DPRINT("ZwSetValueKey('Interrupt') failed (Status %lx)\n", Status
);
2404 ZwClose(ScsiPortKey
);
2408 /* Set 'IOAddress' (REG_DWORD) value (NT4 only) */
2409 UlongData
= ScsiPortConvertPhysicalAddressToUlong(DeviceExtension
->PortConfig
->AccessRanges
[0].RangeStart
);
2410 DPRINT(" IOAddress = %lx\n", UlongData
);
2411 RtlInitUnicodeString(&ValueName
,
2413 Status
= ZwSetValueKey(ScsiPortKey
,
2419 if (!NT_SUCCESS(Status
))
2421 DPRINT("ZwSetValueKey('IOAddress') failed (Status %lx)\n", Status
);
2422 ZwClose(ScsiPortKey
);
2426 /* Enumerate buses */
2427 for (BusNumber
= 0; BusNumber
< DeviceExtension
->PortConfig
->NumberOfBuses
; BusNumber
++)
2429 /* Create 'Scsi Bus X' key */
2430 DPRINT(" Scsi Bus %lu\n", BusNumber
);
2431 swprintf(NameBuffer
,
2434 RtlInitUnicodeString(&KeyName
,
2436 InitializeObjectAttributes(&ObjectAttributes
,
2441 Status
= ZwCreateKey(&ScsiBusKey
,
2446 REG_OPTION_VOLATILE
,
2448 if (!NT_SUCCESS(Status
))
2450 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status
);
2454 /* Create 'Initiator Id X' key */
2455 DPRINT(" Initiator Id %u\n",
2456 DeviceExtension
->PortConfig
->InitiatorBusId
[BusNumber
]);
2457 swprintf(NameBuffer
,
2459 (unsigned int)(UCHAR
)DeviceExtension
->PortConfig
->InitiatorBusId
[BusNumber
]);
2460 RtlInitUnicodeString(&KeyName
,
2462 InitializeObjectAttributes(&ObjectAttributes
,
2467 Status
= ZwCreateKey(&ScsiInitiatorKey
,
2472 REG_OPTION_VOLATILE
,
2474 if (!NT_SUCCESS(Status
))
2476 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status
);
2480 /* FIXME: Are there any initiator values (??) */
2482 ZwClose(ScsiInitiatorKey
);
2483 ScsiInitiatorKey
= NULL
;
2486 /* Enumerate targets */
2487 CurrentTarget
= (ULONG
)-1;
2488 ScsiTargetKey
= NULL
;
2489 for (Target
= 0; Target
< DeviceExtension
->PortConfig
->MaximumNumberOfTargets
; Target
++)
2491 for (Lun
= 0; Lun
< SCSI_MAXIMUM_LOGICAL_UNITS
; Lun
++)
2493 LunExtension
= SpiGetLunExtension(DeviceExtension
,
2497 if (LunExtension
!= NULL
)
2499 if (Target
!= CurrentTarget
)
2501 /* Close old target key */
2502 if (ScsiTargetKey
!= NULL
)
2504 ZwClose(ScsiTargetKey
);
2505 ScsiTargetKey
= NULL
;
2508 /* Create 'Target Id X' key */
2509 DPRINT(" Target Id %lu\n", Target
);
2510 swprintf(NameBuffer
,
2513 RtlInitUnicodeString(&KeyName
,
2515 InitializeObjectAttributes(&ObjectAttributes
,
2520 Status
= ZwCreateKey(&ScsiTargetKey
,
2525 REG_OPTION_VOLATILE
,
2527 if (!NT_SUCCESS(Status
))
2529 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status
);
2533 CurrentTarget
= Target
;
2536 /* Create 'Logical Unit Id X' key */
2537 DPRINT(" Logical Unit Id %lu\n", Lun
);
2538 swprintf(NameBuffer
,
2539 L
"Logical Unit Id %lu",
2541 RtlInitUnicodeString(&KeyName
,
2543 InitializeObjectAttributes(&ObjectAttributes
,
2548 Status
= ZwCreateKey(&ScsiLunKey
,
2553 REG_OPTION_VOLATILE
,
2555 if (!NT_SUCCESS(Status
))
2557 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status
);
2561 /* Set 'Identifier' (REG_SZ) value */
2562 swprintf(NameBuffer
,
2564 LunExtension
->InquiryData
.VendorId
,
2565 LunExtension
->InquiryData
.ProductId
,
2566 LunExtension
->InquiryData
.ProductRevisionLevel
);
2567 DPRINT(" Identifier = '%S'\n", NameBuffer
);
2568 RtlInitUnicodeString(&ValueName
,
2570 Status
= ZwSetValueKey(ScsiLunKey
,
2575 (wcslen(NameBuffer
) + 1) * sizeof(WCHAR
));
2576 if (!NT_SUCCESS(Status
))
2578 DPRINT("ZwSetValueKey('Identifier') failed (Status %lx)\n", Status
);
2582 /* Set 'Type' (REG_SZ) value */
2583 switch (LunExtension
->InquiryData
.DeviceType
)
2586 TypeName
= L
"DiskPeripheral";
2589 TypeName
= L
"TapePeripheral";
2592 TypeName
= L
"PrinterPeripheral";
2595 TypeName
= L
"WormPeripheral";
2598 TypeName
= L
"CdRomPeripheral";
2601 TypeName
= L
"ScannerPeripheral";
2604 TypeName
= L
"OpticalDiskPeripheral";
2607 TypeName
= L
"MediumChangerPeripheral";
2610 TypeName
= L
"CommunicationPeripheral";
2613 TypeName
= L
"OtherPeripheral";
2616 DPRINT(" Type = '%S'\n", TypeName
);
2617 RtlInitUnicodeString(&ValueName
,
2619 Status
= ZwSetValueKey(ScsiLunKey
,
2624 (wcslen(TypeName
) + 1) * sizeof(WCHAR
));
2625 if (!NT_SUCCESS(Status
))
2627 DPRINT("ZwSetValueKey('Type') failed (Status %lx)\n", Status
);
2631 ZwClose(ScsiLunKey
);
2636 /* Close old target key */
2637 if (ScsiTargetKey
!= NULL
)
2639 ZwClose(ScsiTargetKey
);
2640 ScsiTargetKey
= NULL
;
2644 ZwClose(ScsiBusKey
);
2649 if (ScsiLunKey
!= NULL
)
2650 ZwClose (ScsiLunKey
);
2652 if (ScsiInitiatorKey
!= NULL
)
2653 ZwClose (ScsiInitiatorKey
);
2655 if (ScsiTargetKey
!= NULL
)
2656 ZwClose (ScsiTargetKey
);
2658 if (ScsiBusKey
!= NULL
)
2659 ZwClose (ScsiBusKey
);
2661 if (ScsiPortKey
!= NULL
)
2662 ZwClose (ScsiPortKey
);
2664 DPRINT("SpiBuildDeviceMap() done\n");