* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-/* $Id$
- *
+/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Storage Stack
* FILE: drivers/storage/scsiport/scsiport.c
#include "scsiport_int.h"
-#ifdef _MSC_VER
- #define STDCALL
- #define DDKAPI
-#endif
-
ULONG InternalDebugLevel = 0x00;
/* TYPES *********************************************************************/
IN ULONG BusNumber,
IN OUT PPCI_SLOT_NUMBER NextSlotNumber);
-static NTSTATUS STDCALL
+static NTSTATUS NTAPI
ScsiPortCreateClose(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
static DRIVER_DISPATCH ScsiPortDispatchScsi;
-static NTSTATUS STDCALL
+static NTSTATUS NTAPI
ScsiPortDispatchScsi(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
-static NTSTATUS STDCALL
+static NTSTATUS NTAPI
ScsiPortDeviceControl(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
static DRIVER_STARTIO ScsiPortStartIo;
-static VOID STDCALL
+static VOID NTAPI
ScsiPortStartIo(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
-static BOOLEAN STDCALL
+static BOOLEAN NTAPI
ScsiPortStartPacket(IN OUT PVOID Context);
+IO_ALLOCATION_ACTION
+NTAPI
+SpiAdapterControl(PDEVICE_OBJECT DeviceObject, PIRP Irp,
+ PVOID MapRegisterBase, PVOID Context);
static PSCSI_PORT_LUN_EXTENSION
SpiAllocateLunExtension (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension);
IN UCHAR TargetId,
IN UCHAR Lun);
+static PSCSI_REQUEST_BLOCK_INFO
+SpiAllocateSrbStructures(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
+ PSCSI_PORT_LUN_EXTENSION LunExtension,
+ PSCSI_REQUEST_BLOCK Srb);
+
static NTSTATUS
SpiSendInquiry (IN PDEVICE_OBJECT DeviceObject,
IN PSCSI_LUN_INFO LunInfo);
IN PIRP Irp);
static PSCSI_REQUEST_BLOCK_INFO
-SpiGetSrbData(IN PVOID DeviceExtension,
+SpiGetSrbData(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
IN UCHAR PathId,
IN UCHAR TargetId,
IN UCHAR Lun,
IN UCHAR QueueTag);
-static KSERVICE_ROUTINE ScsiPortIsr;
-static BOOLEAN STDCALL
+static BOOLEAN NTAPI
ScsiPortIsr(IN PKINTERRUPT Interrupt,
IN PVOID ServiceContext);
-static VOID STDCALL
+static VOID NTAPI
ScsiPortDpcForIsr(IN PKDPC Dpc,
IN PDEVICE_OBJECT DpcDeviceObject,
IN PIRP DpcIrp,
IN PVOID DpcContext);
-static VOID STDCALL
+static VOID NTAPI
ScsiPortIoTimer(PDEVICE_OBJECT DeviceObject,
PVOID Context);
+IO_ALLOCATION_ACTION
+NTAPI
+ScsiPortAllocateAdapterChannel(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PVOID MapRegisterBase,
+ IN PVOID Context);
+
static NTSTATUS
SpiBuildDeviceMap (PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
PUNICODE_STRING RegistryPath);
IN PSCSI_REQUEST_BLOCK Srb);
static IO_COMPLETION_ROUTINE SpiCompletionRoutine;
-NTSTATUS STDCALL
+NTSTATUS NTAPI
SpiCompletionRoutine(PDEVICE_OBJECT DeviceObject,
PIRP Irp,
PVOID Context);
static VOID
-STDCALL
+NTAPI
SpiProcessCompletedRequest(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
IN PSCSI_REQUEST_BLOCK_INFO SrbInfo,
OUT PBOOLEAN NeedToCallStartIo);
-VOID STDCALL
+VOID NTAPI
SpiGetNextRequestFromLun(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
IN PSCSI_PORT_LUN_EXTENSION LunExtension);
-VOID STDCALL
+VOID NTAPI
SpiMiniportTimerDpc(IN struct _KDPC *Dpc,
IN PVOID DeviceObject,
IN PVOID SystemArgument1,
PPORT_CONFIGURATION_INFORMATION ConfigInfo,
BOOLEAN FirstCall);
-NTSTATUS STDCALL
+NTSTATUS NTAPI
SpQueryDeviceCallout(IN PVOID Context,
IN PUNICODE_STRING PathName,
IN INTERFACE_TYPE BusType,
SpiHandleAttachRelease(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
PIRP Irp);
+static NTSTATUS
+SpiAllocateCommonBuffer(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension, ULONG NonCachedSize);
+
+
/* FUNCTIONS *****************************************************************/
* Status.
*/
-NTSTATUS STDCALL
+NTSTATUS NTAPI
DriverEntry(IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath)
{
DbgPrint(Buffer);
}
+/* An internal helper function for ScsiPortCompleteRequest */
+VOID
+NTAPI
+SpiCompleteRequest(IN PVOID HwDeviceExtension,
+ IN PSCSI_REQUEST_BLOCK_INFO SrbInfo,
+ IN UCHAR SrbStatus)
+{
+ PSCSI_REQUEST_BLOCK Srb;
+
+ /* Get current SRB */
+ Srb = SrbInfo->Srb;
+
+ /* Return if there is no SRB or it is not active */
+ if (!Srb || !(Srb->SrbFlags & SRB_FLAGS_IS_ACTIVE)) return;
+
+ /* Set status */
+ Srb->SrbStatus = SrbStatus;
+
+ /* Set data transfered to 0 */
+ Srb->DataTransferLength = 0;
+
+ /* Notify */
+ ScsiPortNotification(RequestComplete,
+ HwDeviceExtension,
+ Srb);
+}
/*
* @unimplemented
*/
-VOID STDCALL
+VOID NTAPI
ScsiPortCompleteRequest(IN PVOID HwDeviceExtension,
- IN UCHAR PathId,
- IN UCHAR TargetId,
- IN UCHAR Lun,
- IN UCHAR SrbStatus)
+ IN UCHAR PathId,
+ IN UCHAR TargetId,
+ IN UCHAR Lun,
+ IN UCHAR SrbStatus)
{
- DPRINT("ScsiPortCompleteRequest()\n");
- UNIMPLEMENTED;
+ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
+ PSCSI_PORT_LUN_EXTENSION LunExtension;
+ PSCSI_REQUEST_BLOCK_INFO SrbInfo;
+ PLIST_ENTRY ListEntry;
+ ULONG BusNumber;
+ ULONG Target;
+
+ DPRINT("ScsiPortCompleteRequest() called\n");
+
+ DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
+ SCSI_PORT_DEVICE_EXTENSION,
+ MiniPortDeviceExtension);
+
+ /* Go through all buses */
+ for (BusNumber = 0; BusNumber < 8; BusNumber++)
+ {
+ /* Go through all targets */
+ for (Target = 0; Target < DeviceExtension->MaxTargedIds; Target++)
+ {
+ /* Get logical unit list head */
+ LunExtension = DeviceExtension->LunExtensionList[Target % 8];
+
+ /* Go through all logical units */
+ while (LunExtension)
+ {
+ /* Now match what caller asked with what we are at now */
+ if ((PathId == SP_UNTAGGED || PathId == LunExtension->PathId) &&
+ (TargetId == SP_UNTAGGED || TargetId == LunExtension->TargetId) &&
+ (Lun == SP_UNTAGGED || Lun == LunExtension->Lun))
+ {
+ /* Yes, that's what caller asked for. Complete abort requests */
+ if (LunExtension->CompletedAbortRequests)
+ {
+ /* TODO: Save SrbStatus in this request */
+ DPRINT1("Completing abort request without setting SrbStatus!\n");
+
+ /* Issue a notification request */
+ ScsiPortNotification(RequestComplete,
+ HwDeviceExtension,
+ LunExtension->CompletedAbortRequests);
+ }
+
+ /* Complete the request using our helper */
+ SpiCompleteRequest(HwDeviceExtension,
+ &LunExtension->SrbInfo,
+ SrbStatus);
+
+ /* Go through the queue and complete everything there too */
+ ListEntry = LunExtension->SrbInfo.Requests.Flink;
+ while (ListEntry != &LunExtension->SrbInfo.Requests)
+ {
+ /* Get the actual SRB info entry */
+ SrbInfo = CONTAINING_RECORD(ListEntry,
+ SCSI_REQUEST_BLOCK_INFO,
+ Requests);
+
+ /* Complete it */
+ SpiCompleteRequest(HwDeviceExtension,
+ SrbInfo,
+ SrbStatus);
+
+ /* Advance to the next request in queue */
+ ListEntry = SrbInfo->Requests.Flink;
+ }
+ }
+
+ /* Advance to the next one */
+ LunExtension = LunExtension->Next;
+ }
+ }
+ }
}
/*
* @unimplemented
*/
-VOID STDCALL
+VOID NTAPI
ScsiPortFlushDma(IN PVOID HwDeviceExtension)
{
DPRINT("ScsiPortFlushDma()\n");
/*
* @implemented
*/
-VOID STDCALL
+VOID NTAPI
ScsiPortFreeDeviceBase(IN PVOID HwDeviceExtension,
IN PVOID MappedAddress)
{
SCSI_PORT_DEVICE_EXTENSION,
MiniPortDeviceExtension);
-
/* Initialize our pointers */
NextMa = DeviceExtension->MappedAddressList;
LastMa = NextMa;
/*
* @implemented
*/
-ULONG STDCALL
+ULONG NTAPI
ScsiPortGetBusData(IN PVOID DeviceExtension,
IN ULONG BusDataType,
IN ULONG SystemIoBusNumber,
IN PVOID Buffer,
IN ULONG Length)
{
- return(HalGetBusData(BusDataType,
- SystemIoBusNumber,
- SlotNumber,
- Buffer,
- Length));
+ DPRINT("ScsiPortGetBusData()\n");
+
+ if (Length)
+ {
+ /* If Length is non-zero, just forward the call to
+ HalGetBusData() function */
+ return HalGetBusData(BusDataType,
+ SystemIoBusNumber,
+ SlotNumber,
+ Buffer,
+ Length);
+ }
+
+ /* We have a more complex case here */
+ UNIMPLEMENTED;
+ return 0;
}
+/*
+ * @implemented
+ */
+ULONG NTAPI
+ScsiPortSetBusDataByOffset(IN PVOID DeviceExtension,
+ IN ULONG BusDataType,
+ IN ULONG SystemIoBusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length)
+{
+ DPRINT("ScsiPortSetBusDataByOffset()\n");
+ return HalSetBusDataByOffset(BusDataType,
+ SystemIoBusNumber,
+ SlotNumber,
+ Buffer,
+ Offset,
+ Length);
+}
/*
* @implemented
*/
-PVOID STDCALL
+PVOID NTAPI
ScsiPortGetDeviceBase(IN PVOID HwDeviceExtension,
IN INTERFACE_TYPE BusType,
IN ULONG SystemIoBusNumber,
/* i/o space */
if (AddressSpace != 0)
- return((PVOID)TranslatedAddress.u.LowPart);
+ return((PVOID)(ULONG_PTR)TranslatedAddress.QuadPart);
MappedAddress = MmMapIoSpace(TranslatedAddress,
NumberOfBytes,
}
/*
- * @implemented
+ * @unimplemented
*/
-PVOID STDCALL
+PVOID NTAPI
ScsiPortGetLogicalUnit(IN PVOID HwDeviceExtension,
IN UCHAR PathId,
IN UCHAR TargetId,
/*
- * @unimplemented
+ * @implemented
*/
-SCSI_PHYSICAL_ADDRESS STDCALL
+SCSI_PHYSICAL_ADDRESS NTAPI
ScsiPortGetPhysicalAddress(IN PVOID HwDeviceExtension,
- IN PSCSI_REQUEST_BLOCK Srb OPTIONAL,
- IN PVOID VirtualAddress,
- OUT ULONG *Length)
+ IN PSCSI_REQUEST_BLOCK Srb OPTIONAL,
+ IN PVOID VirtualAddress,
+ OUT ULONG *Length)
{
- PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
- SCSI_PHYSICAL_ADDRESS PhysicalAddress;
- SCSI_PHYSICAL_ADDRESS NextPhysicalAddress;
- ULONG BufferLength = 0;
- ULONG Offset;
- PVOID EndAddress;
-
- DPRINT("ScsiPortGetPhysicalAddress(%p %p %p %p)\n",
- HwDeviceExtension, Srb, VirtualAddress, Length);
+ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
+ SCSI_PHYSICAL_ADDRESS PhysicalAddress;
+ ULONG BufferLength = 0;
+ ULONG Offset;
+ PSCSI_SG_ADDRESS SGList;
+ PSCSI_REQUEST_BLOCK_INFO SrbInfo;
- DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
- SCSI_PORT_DEVICE_EXTENSION,
- MiniPortDeviceExtension);
+ DPRINT("ScsiPortGetPhysicalAddress(%p %p %p %p)\n",
+ HwDeviceExtension, Srb, VirtualAddress, Length);
- *Length = 0;
+ DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
+ SCSI_PORT_DEVICE_EXTENSION,
+ MiniPortDeviceExtension);
- if (Srb == NULL)
+ if (Srb == NULL || Srb->SenseInfoBuffer == VirtualAddress)
{
- if ((ULONG_PTR)DeviceExtension->VirtualAddress > (ULONG_PTR)VirtualAddress)
- {
- PhysicalAddress.QuadPart = 0ULL;
- return PhysicalAddress;
- }
-
- Offset = (ULONG_PTR)VirtualAddress - (ULONG_PTR)DeviceExtension->VirtualAddress;
- if (Offset >= DeviceExtension->CommonBufferLength)
- {
- PhysicalAddress.QuadPart = 0ULL;
- return PhysicalAddress;
- }
+ /* Simply look it up in the allocated common buffer */
+ Offset = (PUCHAR)VirtualAddress - (PUCHAR)DeviceExtension->SrbExtensionBuffer;
- PhysicalAddress.QuadPart =
- DeviceExtension->PhysicalAddress.QuadPart + (ULONGLONG)Offset;
- BufferLength = DeviceExtension->CommonBufferLength - Offset;
+ BufferLength = DeviceExtension->CommonBufferLength - Offset;
+ PhysicalAddress.QuadPart = DeviceExtension->PhysicalAddress.QuadPart + Offset;
}
- else
+ else if (DeviceExtension->MapRegisters)
{
- EndAddress = (PVOID)((ULONG_PTR)Srb->DataBuffer + Srb->DataTransferLength);
- if (VirtualAddress == NULL)
- {
- VirtualAddress = Srb->DataBuffer;
- }
- else if (VirtualAddress < Srb->DataBuffer || VirtualAddress >= EndAddress)
- {
- PhysicalAddress.QuadPart = 0LL;
- return PhysicalAddress;
- }
-
- PhysicalAddress = MmGetPhysicalAddress(VirtualAddress);
- if (PhysicalAddress.QuadPart == 0LL)
- {
- return PhysicalAddress;
- }
+ /* Scatter-gather list must be used */
+ SrbInfo = SpiGetSrbData(DeviceExtension,
+ Srb->PathId,
+ Srb->TargetId,
+ Srb->Lun,
+ Srb->QueueTag);
+
+ SGList = SrbInfo->ScatterGather;
+
+ /* Find needed item in the SG list */
+ Offset = (PCHAR)VirtualAddress - (PCHAR)Srb->DataBuffer;
+ while (Offset >= SGList->Length)
+ {
+ Offset -= SGList->Length;
+ SGList++;
+ }
- Offset = (ULONG_PTR)VirtualAddress & (PAGE_SIZE - 1);
-#if 1
- /*
- * FIXME:
- * MmGetPhysicalAddress doesn't return the offset within the page.
- * We must set the correct offset.
- */
- PhysicalAddress.u.LowPart = (PhysicalAddress.u.LowPart & ~(PAGE_SIZE - 1)) + Offset;
-#endif
- BufferLength += PAGE_SIZE - Offset;
- while ((ULONG_PTR)VirtualAddress + BufferLength < (ULONG_PTR)EndAddress)
- {
- NextPhysicalAddress = MmGetPhysicalAddress((PVOID)((ULONG_PTR)VirtualAddress + BufferLength));
- if (PhysicalAddress.QuadPart + (ULONGLONG)BufferLength != NextPhysicalAddress.QuadPart)
- {
- break;
- }
- BufferLength += PAGE_SIZE;
- }
- if ((ULONG_PTR)VirtualAddress + BufferLength >= (ULONG_PTR)EndAddress)
- {
- BufferLength = (ULONG_PTR)EndAddress - (ULONG_PTR)VirtualAddress;
- }
+ /* We're done, store length and physical address */
+ BufferLength = SGList->Length - Offset;
+ PhysicalAddress.QuadPart = SGList->PhysicalAddress.QuadPart + Offset;
+ }
+ else
+ {
+ /* Nothing */
+ *Length = 0;
+ PhysicalAddress.QuadPart = (LONGLONG)(SP_UNINITIALIZED_VALUE);
}
- *Length = BufferLength;
-
- return PhysicalAddress;
+ *Length = BufferLength;
+ return PhysicalAddress;
}
/*
* @unimplemented
*/
-PSCSI_REQUEST_BLOCK STDCALL
+PSCSI_REQUEST_BLOCK NTAPI
ScsiPortGetSrb(IN PVOID DeviceExtension,
IN UCHAR PathId,
IN UCHAR TargetId,
/*
* @implemented
*/
-PVOID STDCALL
+PVOID NTAPI
ScsiPortGetUncachedExtension(IN PVOID HwDeviceExtension,
IN PPORT_CONFIGURATION_INFORMATION ConfigInfo,
IN ULONG NumberOfBytes)
{
- PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
- DEVICE_DESCRIPTION DeviceDescription;
+ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
+ DEVICE_DESCRIPTION DeviceDescription;
+ ULONG MapRegistersCount;
+ NTSTATUS Status;
- DPRINT("ScsiPortGetUncachedExtension(%p %p %lu)\n",
- HwDeviceExtension, ConfigInfo, NumberOfBytes);
+ DPRINT("ScsiPortGetUncachedExtension(%p %p %lu)\n",
+ HwDeviceExtension, ConfigInfo, NumberOfBytes);
- DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
- SCSI_PORT_DEVICE_EXTENSION,
- MiniPortDeviceExtension);
+ DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
+ SCSI_PORT_DEVICE_EXTENSION,
+ MiniPortDeviceExtension);
- /* Check for allocated common DMA buffer */
- if (DeviceExtension->VirtualAddress != NULL)
- {
- DPRINT1("The HBA has already got a common DMA buffer!\n");
- return NULL;
- }
-
- /* Check for DMA adapter object */
- if (DeviceExtension->AdapterObject == NULL)
- {
- /* Initialize DMA adapter description */
- RtlZeroMemory(&DeviceDescription,
- sizeof(DEVICE_DESCRIPTION));
- DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION;
- DeviceDescription.Master = ConfigInfo->Master;
- DeviceDescription.ScatterGather = ConfigInfo->ScatterGather;
- DeviceDescription.DemandMode = ConfigInfo->DemandMode;
- DeviceDescription.Dma32BitAddresses = ConfigInfo->Dma32BitAddresses;
- DeviceDescription.BusNumber = ConfigInfo->SystemIoBusNumber;
- DeviceDescription.DmaChannel = ConfigInfo->DmaChannel;
- DeviceDescription.InterfaceType = ConfigInfo->AdapterInterfaceType;
- DeviceDescription.DmaWidth = ConfigInfo->DmaWidth;
- DeviceDescription.DmaSpeed = ConfigInfo->DmaSpeed;
- DeviceDescription.MaximumLength = ConfigInfo->MaximumTransferLength;
- DeviceDescription.DmaPort = ConfigInfo->DmaPort;
-
- /* Get a DMA adapter object */
- DeviceExtension->AdapterObject = HalGetAdapter(&DeviceDescription,
- &DeviceExtension->MapRegisterCount);
- if (DeviceExtension->AdapterObject == NULL)
- {
- DPRINT1("HalGetAdapter() failed\n");
- return NULL;
- }
+ /* Check for allocated common DMA buffer */
+ if (DeviceExtension->SrbExtensionBuffer != NULL)
+ {
+ DPRINT1("The HBA has already got a common DMA buffer!\n");
+ return NULL;
}
- /* Allocate a common DMA buffer */
- DeviceExtension->CommonBufferLength =
- NumberOfBytes + DeviceExtension->SrbExtensionSize;
- DeviceExtension->VirtualAddress =
- HalAllocateCommonBuffer(DeviceExtension->AdapterObject,
- DeviceExtension->CommonBufferLength,
- &DeviceExtension->PhysicalAddress,
- FALSE);
- if (DeviceExtension->VirtualAddress == NULL)
+ /* Check for DMA adapter object */
+ if (DeviceExtension->AdapterObject == NULL)
{
- DPRINT1("HalAllocateCommonBuffer() failed!\n");
- DeviceExtension->CommonBufferLength = 0;
- return NULL;
+ /* Initialize DMA adapter description */
+ RtlZeroMemory(&DeviceDescription, sizeof(DEVICE_DESCRIPTION));
+
+ DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION;
+ DeviceDescription.Master = ConfigInfo->Master;
+ DeviceDescription.ScatterGather = ConfigInfo->ScatterGather;
+ DeviceDescription.DemandMode = ConfigInfo->DemandMode;
+ DeviceDescription.Dma32BitAddresses = ConfigInfo->Dma32BitAddresses;
+ DeviceDescription.BusNumber = ConfigInfo->SystemIoBusNumber;
+ DeviceDescription.DmaChannel = ConfigInfo->DmaChannel;
+ DeviceDescription.InterfaceType = ConfigInfo->AdapterInterfaceType;
+ DeviceDescription.DmaWidth = ConfigInfo->DmaWidth;
+ DeviceDescription.DmaSpeed = ConfigInfo->DmaSpeed;
+ DeviceDescription.MaximumLength = ConfigInfo->MaximumTransferLength;
+ DeviceDescription.DmaPort = ConfigInfo->DmaPort;
+
+ /* Get a DMA adapter object */
+ DeviceExtension->AdapterObject =
+ HalGetAdapter(&DeviceDescription, &MapRegistersCount);
+
+ /* Fail in case of error */
+ if (DeviceExtension->AdapterObject == NULL)
+ {
+ DPRINT1("HalGetAdapter() failed\n");
+ return NULL;
+ }
+
+ /* Set number of physical breaks */
+ if (ConfigInfo->NumberOfPhysicalBreaks != 0 &&
+ MapRegistersCount > ConfigInfo->NumberOfPhysicalBreaks)
+ {
+ DeviceExtension->PortCapabilities.MaximumPhysicalPages =
+ ConfigInfo->NumberOfPhysicalBreaks;
+ }
+ else
+ {
+ DeviceExtension->PortCapabilities.MaximumPhysicalPages = MapRegistersCount;
+ }
}
- return (PVOID)((ULONG_PTR)DeviceExtension->VirtualAddress +
- DeviceExtension->SrbExtensionSize);
+ /* Update auto request sense feature */
+ DeviceExtension->SupportsAutoSense = ConfigInfo->AutoRequestSense;
+
+ /* Update Srb extension size */
+ if (DeviceExtension->SrbExtensionSize != ConfigInfo->SrbExtensionSize)
+ DeviceExtension->SrbExtensionSize = ConfigInfo->SrbExtensionSize;
+
+ /* Update Srb extension alloc flag */
+ if (ConfigInfo->AutoRequestSense || DeviceExtension->SrbExtensionSize)
+ DeviceExtension->NeedSrbExtensionAlloc = TRUE;
+
+ /* Allocate a common DMA buffer */
+ Status = SpiAllocateCommonBuffer(DeviceExtension, NumberOfBytes);
+
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("SpiAllocateCommonBuffer() failed with Status = 0x%08X!\n", Status);
+ return NULL;
+ }
+
+ return DeviceExtension->NonCachedExtension;
}
+static NTSTATUS
+SpiAllocateCommonBuffer(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension, ULONG NonCachedSize)
+{
+ PVOID *SrbExtension, CommonBuffer;
+ ULONG CommonBufferLength, BufSize;
+
+ /* If size is 0, set it to 16 */
+ if (!DeviceExtension->SrbExtensionSize)
+ DeviceExtension->SrbExtensionSize = 16;
+
+ /* Calculate size */
+ BufSize = DeviceExtension->SrbExtensionSize;
+
+ /* Add autosense data size if needed */
+ if (DeviceExtension->SupportsAutoSense)
+ BufSize += sizeof(SENSE_DATA);
+
+
+ /* Round it */
+ BufSize = (BufSize + sizeof(LONGLONG) - 1) & ~(sizeof(LONGLONG) - 1);
+
+ /* Sum up into the total common buffer length, and round it to page size */
+ CommonBufferLength =
+ ROUND_TO_PAGES(NonCachedSize + BufSize * DeviceExtension->RequestsNumber);
+
+ /* Allocate it */
+ if (!DeviceExtension->AdapterObject)
+ {
+ /* From nonpaged pool if there is no DMA */
+ CommonBuffer = ExAllocatePoolWithTag(NonPagedPool, CommonBufferLength, TAG_SCSIPORT);
+ }
+ else
+ {
+ /* Perform a full request since we have a DMA adapter*/
+ CommonBuffer = HalAllocateCommonBuffer(DeviceExtension->AdapterObject,
+ CommonBufferLength,
+ &DeviceExtension->PhysicalAddress,
+ FALSE );
+ }
+
+ /* Fail in case of error */
+ if (!CommonBuffer)
+ return STATUS_INSUFFICIENT_RESOURCES;
+
+ /* Zero it */
+ RtlZeroMemory(CommonBuffer, CommonBufferLength);
+
+ /* Store its size in Device Extension */
+ DeviceExtension->CommonBufferLength = CommonBufferLength;
+
+ /* SrbExtension buffer is located at the beginning of the buffer */
+ DeviceExtension->SrbExtensionBuffer = CommonBuffer;
+
+ /* Non-cached extension buffer is located at the end of
+ the common buffer */
+ if (NonCachedSize)
+ {
+ CommonBufferLength -= NonCachedSize;
+ DeviceExtension->NonCachedExtension = (PUCHAR)CommonBuffer + CommonBufferLength;
+ }
+ else
+ {
+ DeviceExtension->NonCachedExtension = NULL;
+ }
+
+ if (DeviceExtension->NeedSrbExtensionAlloc)
+ {
+ /* Look up how many SRB data structures we need */
+ DeviceExtension->SrbDataCount = CommonBufferLength / BufSize;
+
+ /* Initialize the free SRB extensions list */
+ SrbExtension = (PVOID *)CommonBuffer;
+ DeviceExtension->FreeSrbExtensions = SrbExtension;
+
+ /* Fill the remainding pointers (if we have more than 1 SRB) */
+ while (CommonBufferLength >= 2 * BufSize)
+ {
+ *SrbExtension = (PVOID*)((PCHAR)SrbExtension + BufSize);
+ SrbExtension = *SrbExtension;
+
+ CommonBufferLength -= BufSize;
+ }
+ }
+
+ return STATUS_SUCCESS;
+}
+
+
/*
* @implemented
*/
-PVOID STDCALL
+PVOID NTAPI
ScsiPortGetVirtualAddress(IN PVOID HwDeviceExtension,
- IN SCSI_PHYSICAL_ADDRESS PhysicalAddress)
+ IN SCSI_PHYSICAL_ADDRESS PhysicalAddress)
{
- PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
- ULONG Offset;
+ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
+ ULONG Offset;
- DPRINT("ScsiPortGetVirtualAddress(%p %I64x)\n",
- HwDeviceExtension, PhysicalAddress.QuadPart);
+ DPRINT("ScsiPortGetVirtualAddress(%p %I64x)\n",
+ HwDeviceExtension, PhysicalAddress.QuadPart);
- DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
- SCSI_PORT_DEVICE_EXTENSION,
- MiniPortDeviceExtension);
+ DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
+ SCSI_PORT_DEVICE_EXTENSION,
+ MiniPortDeviceExtension);
- if (DeviceExtension->PhysicalAddress.QuadPart > PhysicalAddress.QuadPart)
- return NULL;
+ if (DeviceExtension->PhysicalAddress.QuadPart > PhysicalAddress.QuadPart)
+ return NULL;
- Offset = (ULONG)(PhysicalAddress.QuadPart - DeviceExtension->PhysicalAddress.QuadPart);
- if (Offset >= DeviceExtension->CommonBufferLength)
- return NULL;
+ Offset = (ULONG)(PhysicalAddress.QuadPart - DeviceExtension->PhysicalAddress.QuadPart);
+
+ if (Offset >= DeviceExtension->CommonBufferLength)
+ return NULL;
- return (PVOID)((ULONG_PTR)DeviceExtension->VirtualAddress + Offset);
+ return (PVOID)((ULONG_PTR)DeviceExtension->SrbExtensionBuffer + Offset);
}
static VOID
if (!NT_SUCCESS(Status))
{
- DPRINT1("Unable to open driver's registry key %wZ, status 0x%08x\n", RegistryPath, Status);
+ DPRINT("Unable to open driver's registry key %wZ, status 0x%08x\n", RegistryPath, Status);
ConfigInfo->ServiceKey = NULL;
}
}
}
- /* Open the Device key */
- RtlInitUnicodeString(&KeyName, L"Device");
- InitializeObjectAttributes(&ObjectAttributes,
- &KeyName,
- OBJ_CASE_INSENSITIVE,
- ConfigInfo->ServiceKey,
- NULL);
+ if (ConfigInfo->ServiceKey != NULL)
+ {
+ /* Open the Device key */
+ RtlInitUnicodeString(&KeyName, L"Device");
+ InitializeObjectAttributes(&ObjectAttributes,
+ &KeyName,
+ OBJ_CASE_INSENSITIVE,
+ ConfigInfo->ServiceKey,
+ NULL);
- /* We don't check for failure here - not needed */
- ZwOpenKey(&ConfigInfo->DeviceKey,
- KEY_READ,
- &ObjectAttributes);
+ /* We don't check for failure here - not needed */
+ ZwOpenKey(&ConfigInfo->DeviceKey,
+ KEY_READ,
+ &ObjectAttributes);
+ }
}
* @implemented
*/
-ULONG STDCALL
+ULONG NTAPI
ScsiPortInitialize(IN PVOID Argument1,
IN PVOID Argument2,
IN struct _HW_INITIALIZATION_DATA *HwInitializationData,
FirstConfigCall);
if (!NT_SUCCESS(Status))
+ {
+ DPRINT("SpiCreatePortConfig() failed with Status 0x%08X\n", Status);
break;
+ }
/* Allocate and initialize port configuration info */
PortConfigSize = (sizeof(PORT_CONFIGURATION_INFORMATION) +
PortConfig->AccessRanges = (PVOID)(PortConfig+1);
/* Align to LONGLONG */
- PortConfig->AccessRanges = (PVOID)((ULONG)(PortConfig->AccessRanges) + 7);
- PortConfig->AccessRanges = (PVOID)((ULONG)(PortConfig->AccessRanges) & ~7);
+ PortConfig->AccessRanges = (PVOID)((ULONG_PTR)(PortConfig->AccessRanges) + 7);
+ PortConfig->AccessRanges = (PVOID)((ULONG_PTR)(PortConfig->AccessRanges) & ~7);
/* Copy the data */
RtlCopyMemory(PortConfig->AccessRanges,
DeviceExtension->SupportsAutoSense = PortConfig->AutoRequestSense;
DeviceExtension->NeedSrbExtensionAlloc = TRUE;
- //Status = STATUS_UNSUCCESFUL;
- /* TODO: Allocate common buffer */
- ASSERT(FALSE);
+ /* Allocate common buffer */
+ Status = SpiAllocateCommonBuffer(DeviceExtension, 0);
/* Check for failure */
if (!NT_SUCCESS(Status))
if (ConfigInfo.Parameter != NULL)
ExFreePool(ConfigInfo.Parameter);
- DPRINT("ScsiPortInitialize() done, Status = 0x%08X, DeviceFound = %b!\n",
+ DPRINT("ScsiPortInitialize() done, Status = 0x%08X, DeviceFound = %d!\n",
Status, DeviceFound);
return (DeviceFound == FALSE) ? Status : STATUS_SUCCESS;
LunInfo = DeviceExtension->BusesConfig->BusScanInfo[Bus]->LunInfo;
- while (!LunInfo)
+ while (LunInfo)
{
/* Free current, but save pointer to the next one */
Ptr = LunInfo->Next;
/* Free common buffer (if it exists) */
if (DeviceExtension->SrbExtensionBuffer != NULL &&
- DeviceExtension->CommonBufferSize != 0)
+ DeviceExtension->CommonBufferLength != 0)
{
if (!DeviceExtension->AdapterObject)
{
}
else
{
-#if 0
HalFreeCommonBuffer(DeviceExtension->AdapterObject,
- DeviceExtension->CommonBufferSize,
- DeviceExtension->PhysicalCommonBuffer,
+ DeviceExtension->CommonBufferLength,
+ DeviceExtension->PhysicalAddress,
DeviceExtension->SrbExtensionBuffer,
FALSE);
-#endif
}
}
IoDeleteDevice(DeviceExtension->DeviceObject);
}
-
-
/*
* @unimplemented
*/
-VOID STDCALL
+VOID NTAPI
ScsiPortIoMapTransfer(IN PVOID HwDeviceExtension,
IN PSCSI_REQUEST_BLOCK Srb,
IN PVOID LogicalAddress,
UNIMPLEMENTED;
}
-
/*
* @unimplemented
*/
-VOID STDCALL
+VOID NTAPI
ScsiPortLogError(IN PVOID HwDeviceExtension,
IN PSCSI_REQUEST_BLOCK Srb OPTIONAL,
IN UCHAR PathId,
DPRINT("ScsiPortLogError() done\n");
}
-
/*
* @implemented
*/
-VOID STDCALL
+VOID NTAPI
ScsiPortMoveMemory(OUT PVOID Destination,
IN PVOID Source,
IN ULONG Length)
DeviceExtension->InterruptData.Flags |= SCSI_PORT_NEXT_REQUEST_READY;
break;
- case NextLuRequest:
- {
- UCHAR PathId;
- UCHAR TargetId;
- UCHAR Lun;
+ case NextLuRequest:
+ {
+ UCHAR PathId;
+ UCHAR TargetId;
+ UCHAR Lun;
+ PSCSI_PORT_LUN_EXTENSION LunExtension;
- PathId = (UCHAR) va_arg (ap, int);
- TargetId = (UCHAR) va_arg (ap, int);
- Lun = (UCHAR) va_arg (ap, int);
+ PathId = (UCHAR) va_arg (ap, int);
+ TargetId = (UCHAR) va_arg (ap, int);
+ Lun = (UCHAR) va_arg (ap, int);
- DPRINT1 ("Notify: NextLuRequest(PathId %u TargetId %u Lun %u)\n",
- PathId, TargetId, Lun);
- /* FIXME: Implement it! */
- ASSERT(FALSE);
+ DPRINT("Notify: NextLuRequest(PathId %u TargetId %u Lun %u)\n",
+ PathId, TargetId, Lun);
-// DeviceExtension->IrpFlags |= IRP_FLAG_NEXT;
-// DeviceExtension->IrpFlags |= IRP_FLAG_NEXT_LU;
+ /* Mark it in the flags field */
+ DeviceExtension->InterruptData.Flags |= SCSI_PORT_NEXT_REQUEST_READY;
- /* Hack! */
-// DeviceExtension->IrpFlags |= IRP_FLAG_NEXT;
- }
- break;
+ /* Get the LUN extension */
+ LunExtension = SpiGetLunExtension(DeviceExtension,
+ PathId,
+ TargetId,
+ Lun);
+
+ /* If returned LunExtension is NULL, break out */
+ if (!LunExtension) break;
+
+ /* This request should not be processed if */
+ if ((LunExtension->ReadyLun) ||
+ (LunExtension->SrbInfo.Srb))
+ {
+ /* Nothing to do here */
+ break;
+ }
+
+ /* Add this LUN to the list */
+ LunExtension->ReadyLun = DeviceExtension->InterruptData.ReadyLun;
+ DeviceExtension->InterruptData.ReadyLun = LunExtension;
+ }
+ break;
case ResetDetected:
- DPRINT1("Notify: ResetDetected\n");
- /* FIXME: ??? */
- break;
+ DPRINT("Notify: ResetDetected\n");
+ /* Add RESET flags */
+ DeviceExtension->InterruptData.Flags |=
+ SCSI_PORT_RESET | SCSI_PORT_RESET_REPORTED;
+ break;
default:
DPRINT1 ("Unsupported notification %lu\n", NotificationType);
break;
}
- va_end(ap);
+ va_end(ap);
/* Request a DPC after we're done with the interrupt */
DeviceExtension->InterruptData.Flags |= SCSI_PORT_NOTIFICATION_NEEDED;
}
-
/*
* @implemented
*/
-ULONG STDCALL
-ScsiPortSetBusDataByOffset(IN PVOID DeviceExtension,
- IN ULONG BusDataType,
- IN ULONG SystemIoBusNumber,
- IN ULONG SlotNumber,
- IN PVOID Buffer,
- IN ULONG Offset,
- IN ULONG Length)
-{
- DPRINT("ScsiPortSetBusDataByOffset()\n");
- return(HalSetBusDataByOffset(BusDataType,
- SystemIoBusNumber,
- SlotNumber,
- Buffer,
- Offset,
- Length));
-}
-
-
-/*
- * @implemented
- */
-BOOLEAN STDCALL
+BOOLEAN NTAPI
ScsiPortValidateRange(IN PVOID HwDeviceExtension,
IN INTERFACE_TYPE BusType,
IN ULONG SystemIoBusNumber,
* Status.
*/
-static NTSTATUS STDCALL
+static NTSTATUS NTAPI
ScsiPortCreateClose(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
* NTSTATUS
*/
-static NTSTATUS STDCALL
+static NTSTATUS NTAPI
ScsiPortDispatchScsi(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
* NTSTATUS
*/
-static NTSTATUS STDCALL
+static NTSTATUS NTAPI
ScsiPortDeviceControl(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
DPRINT(" IOCTL_SCSI_GET_DUMP_POINTERS\n");
DumpPointers = (PDUMP_POINTERS)Irp->AssociatedIrp.SystemBuffer;
DumpPointers->DeviceObject = DeviceObject;
-
+
Irp->IoStatus.Information = sizeof(DUMP_POINTERS);
}
break;
}
-static VOID STDCALL
+static VOID NTAPI
ScsiPortStartIo(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PSCSI_REQUEST_BLOCK Srb;
PSCSI_REQUEST_BLOCK_INFO SrbInfo;
LONG CounterResult;
+ NTSTATUS Status;
DPRINT("ScsiPortStartIo() called!\n");
if (DeviceExtension->NeedSrbDataAlloc ||
DeviceExtension->NeedSrbExtensionAlloc)
{
- /* TODO: Implement */
- ASSERT(FALSE);
- SrbInfo = NULL;
+ /* Allocate them */
+ SrbInfo = SpiAllocateSrbStructures(DeviceExtension,
+ LunExtension,
+ Srb);
+
+ /* Couldn't alloc one or both data structures, return */
+ if (SrbInfo == NULL)
+ {
+ /* We have to call IoStartNextPacket, because this request
+ was not started */
+ if (LunExtension->Flags & LUNEX_REQUEST_PENDING)
+ IoStartNextPacket(DeviceObject, FALSE);
+
+ return;
+ }
}
else
{
// Store the MDL virtual address in SrbInfo structure
SrbInfo->DataOffset = MmGetMdlVirtualAddress(Irp->MdlAddress);
- if (DeviceExtension->MapBuffers && Irp->MdlAddress)
+ if (DeviceExtension->MapBuffers)
{
/* Calculate offset within DataBuffer */
SrbInfo->DataOffset = MmGetSystemAddressForMdl(Irp->MdlAddress);
if (DeviceExtension->MapRegisters)
{
-#if 0
/* Calculate number of needed map registers */
SrbInfo->NumberOfMapRegisters = ADDRESS_AND_SIZE_TO_SPAN_PAGES(
Srb->DataBuffer,
/* Control goes to SpiAdapterControl */
return;
-#else
- ASSERT(FALSE);
-#endif
}
}
DeviceExtension->AdapterObject != NULL &&
!DeviceExtension->MapRegisters)
{
-#if 0
IoAllocateAdapterChannel(
DeviceExtension->AdapterObject,
DeviceObject,
DeviceExtension->PortCapabilities.MaximumPhysicalPages,
- ScsiPortAllocationRoutine,
+ ScsiPortAllocateAdapterChannel,
LunExtension
);
return;
-#else
- /* TODO: DMA is not implemented yet */
- ASSERT(FALSE);
-#endif
}
-
KeAcquireSpinLockAtDpcLevel(&DeviceExtension->SpinLock);
if (!KeSynchronizeExecution(DeviceExtension->Interrupt,
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
+ else
+ {
+ /* Release the spinlock only */
+ KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
+ }
- KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
DPRINT("ScsiPortStartIo() done\n");
}
-static BOOLEAN STDCALL
+static BOOLEAN NTAPI
ScsiPortStartPacket(IN OUT PVOID Context)
{
PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
PSCSI_REQUEST_BLOCK Srb;
PDEVICE_OBJECT DeviceObject = (PDEVICE_OBJECT)Context;
PSCSI_PORT_LUN_EXTENSION LunExtension;
+ PSCSI_REQUEST_BLOCK_INFO SrbInfo;
BOOLEAN Result;
BOOLEAN StartTimer;
/* Is this an abort request? */
if (Srb->Function == SRB_FUNCTION_ABORT_COMMAND)
{
- PSCSI_REQUEST_BLOCK_INFO SrbInfo;
-
/* Get pointer to SRB info structure */
SrbInfo = SpiGetSrbData(DeviceExtension,
Srb->PathId,
/* If it's tagged - special thing */
if (Srb->QueueTag != SP_UNTAGGED)
{
- /* TODO: Support tagged requests */
- ASSERT(FALSE);
+ SrbInfo = &DeviceExtension->SrbInfo[Srb->QueueTag - 1];
+
+ /* Chek for consistency */
+ ASSERT(SrbInfo->Requests.Blink == NULL);
+
+ /* Insert it into the list of requests */
+ InsertTailList(&LunExtension->SrbInfo.Requests, &SrbInfo->Requests);
}
}
return Result;
}
+IO_ALLOCATION_ACTION
+NTAPI
+SpiAdapterControl(PDEVICE_OBJECT DeviceObject,
+ PIRP Irp,
+ PVOID MapRegisterBase,
+ PVOID Context)
+{
+ PSCSI_REQUEST_BLOCK Srb;
+ PSCSI_SG_ADDRESS ScatterGatherList;
+ KIRQL CurrentIrql;
+ PIO_STACK_LOCATION IrpStack;
+ ULONG TotalLength = 0;
+ PSCSI_REQUEST_BLOCK_INFO SrbInfo;
+ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
+ PUCHAR DataVA;
+ BOOLEAN WriteToDevice;
+
+ /* Get pointers to SrbInfo and DeviceExtension */
+ SrbInfo = (PSCSI_REQUEST_BLOCK_INFO)Context;
+ DeviceExtension = DeviceObject->DeviceExtension;
+
+ /* Get pointer to SRB */
+ IrpStack = IoGetCurrentIrpStackLocation(Irp);
+ Srb = (PSCSI_REQUEST_BLOCK)IrpStack->Parameters.Others.Argument1;
+
+ /* Depending on the map registers number, we allocate
+ either from NonPagedPool, or from our static list */
+ if (SrbInfo->NumberOfMapRegisters > MAX_SG_LIST)
+ {
+ SrbInfo->ScatterGather = ExAllocatePoolWithTag(
+ NonPagedPool, SrbInfo->NumberOfMapRegisters * sizeof(SCSI_SG_ADDRESS), TAG_SCSIPORT);
+
+ if (SrbInfo->ScatterGather == NULL)
+ ASSERT(FALSE);
+
+ Srb->SrbFlags |= SRB_FLAGS_SGLIST_FROM_POOL;
+ }
+ else
+ {
+ SrbInfo->ScatterGather = SrbInfo->ScatterGatherList;
+ }
+
+ /* Use chosen SG list source */
+ ScatterGatherList = SrbInfo->ScatterGather;
+
+ /* Save map registers base */
+ SrbInfo->BaseOfMapRegister = MapRegisterBase;
+
+ /* Determine WriteToDevice flag */
+ WriteToDevice = Srb->SrbFlags & SRB_FLAGS_DATA_OUT ? TRUE : FALSE;
+
+ /* Get virtual address of the data buffer */
+ DataVA = (PUCHAR)MmGetMdlVirtualAddress(Irp->MdlAddress) +
+ ((PCHAR)Srb->DataBuffer - SrbInfo->DataOffset);
+
+ /* Build the actual SG list */
+ while (TotalLength < Srb->DataTransferLength)
+ {
+ if (!ScatterGatherList)
+ break;
+
+ ScatterGatherList->Length = Srb->DataTransferLength - TotalLength;
+ ScatterGatherList->PhysicalAddress = IoMapTransfer(NULL,
+ Irp->MdlAddress,
+ MapRegisterBase,
+ DataVA + TotalLength,
+ &ScatterGatherList->Length,
+ WriteToDevice);
+
+ TotalLength += ScatterGatherList->Length;
+ ScatterGatherList++;
+ }
+
+ /* Schedule an active request */
+ InterlockedIncrement(&DeviceExtension->ActiveRequestCounter );
+ KeAcquireSpinLock(&DeviceExtension->SpinLock, &CurrentIrql);
+ KeSynchronizeExecution(DeviceExtension->Interrupt,
+ ScsiPortStartPacket,
+ DeviceObject);
+ KeReleaseSpinLock(&DeviceExtension->SpinLock, CurrentIrql);
+
+ return DeallocateObjectKeepRegisters;
+}
+
static PSCSI_PORT_LUN_EXTENSION
SpiAllocateLunExtension (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
{
return NULL;
}
+static PSCSI_REQUEST_BLOCK_INFO
+SpiAllocateSrbStructures(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
+ PSCSI_PORT_LUN_EXTENSION LunExtension,
+ PSCSI_REQUEST_BLOCK Srb)
+{
+ PCHAR SrbExtension;
+ PSCSI_REQUEST_BLOCK_INFO SrbInfo;
+
+ /* Spinlock must be held while this function executes */
+ KeAcquireSpinLockAtDpcLevel(&DeviceExtension->SpinLock);
+
+ /* Allocate SRB data structure */
+ if (DeviceExtension->NeedSrbDataAlloc)
+ {
+ /* Treat the abort request in a special way */
+ if (Srb->Function == SRB_FUNCTION_ABORT_COMMAND)
+ {
+ SrbInfo = SpiGetSrbData(DeviceExtension,
+ Srb->PathId,
+ Srb->TargetId,
+ Srb->Lun,
+ Srb->QueueTag);
+ }
+ else if (Srb->SrbFlags &
+ (SRB_FLAGS_QUEUE_ACTION_ENABLE | SRB_FLAGS_NO_QUEUE_FREEZE) &&
+ !(Srb->SrbFlags & SRB_FLAGS_DISABLE_DISCONNECT)
+ )
+ {
+ /* Do not process tagged commands if need request sense is set */
+ if (LunExtension->Flags & LUNEX_NEED_REQUEST_SENSE)
+ {
+ ASSERT(!(LunExtension->Flags & LUNEX_REQUEST_PENDING));
+
+ LunExtension->PendingRequest = Srb->OriginalRequest;
+ LunExtension->Flags |= LUNEX_REQUEST_PENDING | SCSI_PORT_LU_ACTIVE;
+
+ /* Relese the spinlock and return */
+ KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
+ return NULL;
+ }
+
+ ASSERT(LunExtension->SrbInfo.Srb == NULL);
+ SrbInfo = DeviceExtension->FreeSrbInfo;
+
+ if (SrbInfo == NULL)
+ {
+ /* No SRB structures left in the list. We have to leave
+ and wait while we are called again */
+
+ DeviceExtension->Flags |= SCSI_PORT_REQUEST_PENDING;
+ KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
+ return NULL;
+ }
+
+ DeviceExtension->FreeSrbInfo = (PSCSI_REQUEST_BLOCK_INFO)SrbInfo->Requests.Flink;
+
+ /* QueueTag must never be 0, so +1 to it */
+ Srb->QueueTag = (UCHAR)(SrbInfo - DeviceExtension->SrbInfo) + 1;
+ }
+ else
+ {
+ /* Usual untagged command */
+ if (
+ (!IsListEmpty(&LunExtension->SrbInfo.Requests) ||
+ LunExtension->Flags & LUNEX_NEED_REQUEST_SENSE) &&
+ !(Srb->SrbFlags & SRB_FLAGS_BYPASS_FROZEN_QUEUE)
+ )
+ {
+ /* Mark it as pending and leave */
+ ASSERT(!(LunExtension->Flags & LUNEX_REQUEST_PENDING));
+ LunExtension->Flags |= LUNEX_REQUEST_PENDING | SCSI_PORT_LU_ACTIVE;
+ LunExtension->PendingRequest = Srb->OriginalRequest;
+
+ KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
+ return(NULL);
+ }
+
+ Srb->QueueTag = SP_UNTAGGED;
+ SrbInfo = &LunExtension->SrbInfo;
+ }
+ }
+ else
+ {
+ Srb->QueueTag = SP_UNTAGGED;
+ SrbInfo = &LunExtension->SrbInfo;
+ }
+
+ /* Allocate SRB extension structure */
+ if (DeviceExtension->NeedSrbExtensionAlloc)
+ {
+ /* Check the list of free extensions */
+ SrbExtension = DeviceExtension->FreeSrbExtensions;
+
+ /* If no free extensions... */
+ if (SrbExtension == NULL)
+ {
+ /* Free SRB data */
+ if (Srb->Function != SRB_FUNCTION_ABORT_COMMAND &&
+ Srb->QueueTag != SP_UNTAGGED)
+ {
+ SrbInfo->Requests.Blink = NULL;
+ SrbInfo->Requests.Flink = (PLIST_ENTRY)DeviceExtension->FreeSrbInfo;
+ DeviceExtension->FreeSrbInfo = SrbInfo;
+ }
+
+ /* Return, in order to be called again later */
+ DeviceExtension->Flags |= SCSI_PORT_REQUEST_PENDING;
+ KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
+ return NULL;
+ }
+
+ /* Remove that free SRB extension from the list (since
+ we're going to use it) */
+ DeviceExtension->FreeSrbExtensions = *((PVOID *)SrbExtension);
+
+ /* Spinlock can be released now */
+ KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
+
+ Srb->SrbExtension = SrbExtension;
+
+ if (Srb->SenseInfoBuffer != NULL &&
+ DeviceExtension->SupportsAutoSense)
+ {
+ /* Store pointer to the SenseInfo buffer */
+ SrbInfo->SaveSenseRequest = Srb->SenseInfoBuffer;
+
+ /* Does data fit the buffer? */
+ if (Srb->SenseInfoBufferLength > sizeof(SENSE_DATA))
+ {
+ /* No, disabling autosense at all */
+ Srb->SrbFlags |= SRB_FLAGS_DISABLE_AUTOSENSE;
+ }
+ else
+ {
+ /* Yes, update the buffer pointer */
+ Srb->SenseInfoBuffer = SrbExtension + DeviceExtension->SrbExtensionSize;
+ }
+ }
+ }
+ else
+ {
+ /* Cleanup... */
+ Srb->SrbExtension = NULL;
+ KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
+ }
+
+ return SrbInfo;
+}
+
static NTSTATUS
SpiSendInquiry (IN PDEVICE_OBJECT DeviceObject,
/* Scan all logical units */
for (Lun = 0; Lun < SCSI_MAXIMUM_LOGICAL_UNITS; Lun++)
{
- if (!LunExtension)
+ if ((!LunExtension) || (!LunInfo))
break;
/* Add extension to the list */
/* Check if this device is unsupported */
if (InquiryData->DeviceTypeQualifier == DEVICE_QUALIFIER_NOT_SUPPORTED)
{
- DeviceExtension->LunExtensionList[Hint] =
+ DeviceExtension->LunExtensionList[Hint] =
DeviceExtension->LunExtensionList[Hint]->Next;
continue;
else
{
/* Remove this LUN from the list */
- DeviceExtension->LunExtensionList[Hint] =
+ DeviceExtension->LunExtensionList[Hint] =
DeviceExtension->LunExtensionList[Hint]->Next;
/* Decide whether we are continuing or not */
/* Calculate data size */
Length = sizeof(SCSI_ADAPTER_BUS_INFO) + (BusCount - 1) *
sizeof(SCSI_BUS_DATA);
-
+
Length += InquiryDataSize * LunCount;
/* Check, if all data is going to fit into provided buffer */
}
static PSCSI_REQUEST_BLOCK_INFO
-SpiGetSrbData(IN PVOID DeviceExtension,
+SpiGetSrbData(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
IN UCHAR PathId,
IN UCHAR TargetId,
IN UCHAR Lun,
}
else
{
- /* TODO: Implement when we have it */
- ASSERT(FALSE);
- return NULL;
+ /* Make sure the tag is valid, if it is - return the data */
+ if (QueueTag > DeviceExtension->SrbDataCount || QueueTag < 1)
+ return NULL;
+ else
+ return &DeviceExtension->SrbInfo[QueueTag -1];
}
}
TRUE,
TRUE);
+ if (!Srb)
+ {
+ DPRINT("SpiSendRequestSense() failed, Srb %p\n", Srb);
+ return;
+ }
+
IrpStack = IoGetNextIrpStackLocation(Irp);
IrpStack->MajorFunction = IRP_MJ_SCSI;
static
VOID
-STDCALL
+NTAPI
SpiProcessCompletedRequest(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
IN PSCSI_REQUEST_BLOCK_INFO SrbInfo,
OUT PBOOLEAN NeedToCallStartIo)
}
}
-
/* Flush adapter if needed */
if (SrbInfo->BaseOfMapRegister)
{
KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
}
- DPRINT("IoCompleting request IRP 0x%08X\n", Irp);
+ DPRINT("IoCompleting request IRP 0x%p\n", Irp);
IoCompleteRequest(Irp, IO_DISK_INCREMENT);
}
NTSTATUS
-STDCALL
+NTAPI
SpiCompletionRoutine(PDEVICE_OBJECT DeviceObject,
PIRP Irp,
PVOID Context)
if (Irp->MdlAddress != NULL)
{
- MmUnlockPages(Irp->MdlAddress);
+ MmUnlockPages(Irp->MdlAddress);
IoFreeMdl(Irp->MdlAddress);
Irp->MdlAddress = NULL;
}
return STATUS_MORE_PROCESSING_REQUIRED;
}
-
-
-static BOOLEAN STDCALL
+static BOOLEAN NTAPI
ScsiPortIsr(IN PKINTERRUPT Interrupt,
IN PVOID ServiceContext)
{
}
BOOLEAN
-STDCALL
+NTAPI
SpiSaveInterruptData(IN PVOID Context)
{
PSCSI_PORT_SAVE_INTERRUPT InterruptContext = Context;
}
VOID
-STDCALL
+NTAPI
SpiGetNextRequestFromLun(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
IN PSCSI_PORT_LUN_EXTENSION LunExtension)
{
// IN PIRP DpcIrp
// IN PVOID DpcContext
//
-static VOID STDCALL
+static VOID NTAPI
ScsiPortDpcForIsr(IN PKDPC Dpc,
IN PDEVICE_OBJECT DpcDeviceObject,
IN PIRP DpcIrp,
}
BOOLEAN
-STDCALL
+NTAPI
SpiProcessTimeout(PVOID ServiceContext)
{
PDEVICE_OBJECT DeviceObject = (PDEVICE_OBJECT)ServiceContext;
BOOLEAN
-STDCALL
+NTAPI
SpiResetBus(PVOID ServiceContext)
{
PRESETBUS_PARAMS ResetParams = (PRESETBUS_PARAMS)ServiceContext;
// IN PVOID Context the Controller extension for the
// controller the device is on
//
-static VOID STDCALL
+static VOID NTAPI
ScsiPortIoTimer(PDEVICE_OBJECT DeviceObject,
PVOID Context)
{
}
VOID
-STDCALL
+NTAPI
SpiMiniportTimerDpc(IN struct _KDPC *Dpc,
IN PVOID DeviceObject,
IN PVOID SystemArgument1,
IN PVOID SystemArgument2)
{
DPRINT1("Miniport timer DPC\n");
+ ASSERT(FALSE);
}
static NTSTATUS
else
{
/* Info was not found, exit */
+ DPRINT1("ZwOpenKey() failed with Status=0x%08X\n", Status);
return STATUS_DEVICE_DOES_NOT_EXIST;
}
}
+ else
+ {
+ DPRINT1("ZwOpenKey() failed with Status=0x%08X\n", Status);
+ }
}
-
/* Look at device params */
Key = NULL;
if (InternalConfigInfo->Parameter)
ANSI_STRING AnsiString;
NTSTATUS Status = STATUS_SUCCESS;
-
KeyValueInformation = (PKEY_VALUE_FULL_INFORMATION) Buffer;
/* Loop through all values in the device node */
}
}
-
NTSTATUS
-STDCALL
+NTAPI
SpQueryDeviceCallout(IN PVOID Context,
IN PUNICODE_STRING PathName,
IN INTERFACE_TYPE BusType,
return STATUS_SUCCESS;
}
+IO_ALLOCATION_ACTION
+NTAPI
+ScsiPortAllocateAdapterChannel(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PVOID MapRegisterBase,
+ IN PVOID Context)
+{
+ KIRQL Irql;
+ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
+
+ /* Guard access with the spinlock */
+ KeAcquireSpinLock(&DeviceExtension->SpinLock, &Irql);
+
+ /* Save MapRegisterBase we've got here */
+ DeviceExtension->MapRegisterBase = MapRegisterBase;
+
+ /* Start pending request */
+ KeSynchronizeExecution(DeviceExtension->Interrupt,
+ ScsiPortStartPacket, DeviceObject);
+
+ /* Release spinlock we took */
+ KeReleaseSpinLock(&DeviceExtension->SpinLock, Irql);
+ return KeepObject;
+}
static
NTSTATUS
case SRB_STATUS_TIMEOUT:
case SRB_STATUS_COMMAND_TIMEOUT:
return STATUS_IO_TIMEOUT;
-
+
case SRB_STATUS_BAD_SRB_BLOCK_LENGTH:
case SRB_STATUS_BAD_FUNCTION:
return STATUS_INVALID_DEVICE_REQUEST;
/*
* @implemented
*/
-ULONG STDCALL
+ULONG NTAPI
ScsiPortConvertPhysicalAddressToUlong(IN SCSI_PHYSICAL_ADDRESS Address)
{
DPRINT("ScsiPortConvertPhysicalAddressToUlong()\n");