IOCTL_SCSI_PASS_THROUGH_DIRECT - NtDoc

Native API online documentation, based on the System Informer (formerly Process Hacker) phnt headers
// ntddscsi.h

// CTL_CODE(0x0004, 0x405, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_SCSI_PASS_THROUGH_DIRECT 0x0004D014
View the official Windows Driver Kit DDI reference

NtDoc

No description available.

Windows Driver Kit DDI reference (ni-ntddscsi-ioctl_scsi_pass_through_direct)

IOCTL_SCSI_PASS_THROUGH_DIRECT IOCTL

Description

Allows an application to send almost any SCSI command to a target device, with the following restrictions:

The calling application creates the SCSI command descriptor block, which can include a request for request-sense data if a CHECK CONDITION occurs. If the CDB requests a data transfer operation, the caller must set up an adapter device aligned buffer from which or into which the miniport driver can transfer data directly. This request is typically used for transferring larger amounts of data (>16K).

Applications can send this request by means of an IRP_MJ_DEVICE_CONTROL request.

Storage class drivers set the minor IRP number to IRP_MN_SCSI_CLASS to indicate that the request has been processed by a storage class driver.

Note The SCSI port driver and SCSI miniport driver models may be altered or unavailable in the future. Instead, we recommend using the Storport driver and Storport miniport driver models.

Parameters

Major code

Input buffer

This structure includes an SCSI CDB, which must be initialized by the caller except for the path, target ID, and LUN, which are filled in by the port driver. For a data-out command, the data to be transferred must be in an adapter device aligned buffer. The DataBuffer member of SCSI_PASS_THROUGH_DIRECT is a pointer to this adapter device aligned buffer. The caller must allocate additional storage, following the SCSI_PASS_THROUGH_DIRECT structure, if the caller asks for request-sense data.

Input buffer length

Parameters.DeviceIoControl.InputBufferLength indicates the size, in bytes, of the buffer at Irp->AssociatedIrp.SystemBuffer, which must be at least (sense data size + sizeof (SCSI_PASS_THROUGH_DIRECT)). The size of the SCSI_PASS_THROUGH_DIRECT structure is fixed.

Output buffer

The port driver returns any request-sense data and the SCSI_PASS_THROUGH_DIRECT structure to the buffer at Irp->AssociatedIrp.SystemBuffer.

Output buffer length

SenseInfoLength and DataTransferLength are updated to indicate the amount of data transferred. The port driver returns any data transferred from the device to the supplied cache-aligned buffer at DataBuffer .

Input/output buffer

Input/output buffer length

Status block

The Information field is set to the number of bytes returned in the output buffer at Irp->AssociatedIrp.SystemBuffer. The Status field is set to STATUS_SUCCESS, or possibly to STATUS_BUFFER_TOO_SMALL or STATUS_INVALID_PARAMETER if the input Length value in SCSI_PASS_THROUGH_DIRECT is improperly set or the buffer specified in DataBuffer is not properly device aligned.

Remarks

For data transfer operations, a buffer with alignment matching the adapter device is required. Applications can retrieve the device alignment mask by issuing an IOCTL_STORAGE_QUERY_PROPERTY control code request with a query type of PropertyStandardQuery and property id of StorageAdapterProperty. The alignment mask is found in the AlignmentMask member of the STORAGE_ADAPTER_DESCRIPTOR structure that is returned. Drivers may also use the value in the AlignmentMask member of the adapter's DeviceObject.

In the following example function, a buffer is prepared as a device aligned data transfer buffer.

PVOID AllocateAlignedBuffer(ULONG size, ULONG AlignmentMask, PVOID *pUnAlignedBuffer)
{
    PVOID AlignedBuffer;
    ULONG_PTR FullWordMask = (ULONG_PTR)AlignmentMask;

    if (AlignmentMask == 0)
    {
        AlignedBuffer = malloc(size);
        // return the original buffer to free later
        *pUnAlignedBuffer = AlignedBuffer;
    }
    else
    {
        // expand the size for the alignment window
        size += AlignmentMask;
        AlignedBuffer = malloc(size);
        // return the original buffer to free later
        *pUnAlignedBuffer = AlignedBuffer;
        // adjust buffer pointer for the desired alignment
        AlignedBuffer = (PVOID)(((ULONG_PTR)AlignedBuffer + FullWordMask) & ~FullWordMask);
    }

    return AlignedBuffer;
}

See also

IOCTL_SCSI_PASS_THROUGH

IOCTL_STORAGE_QUERY_PROPERTY

SCSI_PASS_THROUGH_DIRECT