This IOCTL command passes the built command data block structure with I/O buffer pointers to the lower SCSI layer. Status is returned from the lower SCSI layer to the caller with the ASC and ASCQ values and SenseKey fields. The ASC and ASCQ and sense key fields are valid only when the SenseDataValid field is true.

The data structure is
#define SCSI_PASS_THROUGH _IOWR('P',0x01,SCSIPassThrough) /* Pass Through  */
  typedef struct _SCSIPassThrough
    unchar   CDB[12];              /* Command Data Block */
    unchar   CommandLength;        /* Command Length     */
    unchar * Buffer ;              /* Command Buffer     */
    ulong    BufferLength;         /* Buffer Length             */
    unchar   DataDirection;        /* Data Transfer Direction   */
    ushort   TimeOut;              /* Time Out Value            */
    unchar   TargetStatus;         /* Target Status             */
    unchar   MessageStatus;        /* Message from host adapter */
    unchar   HostStatus;           /* Host status               */
    unchar   DriverStatus;         /* Driver status             */
    unchar   SenseDataValid;       /* Sense Data Valid          */
    unchar   ASC;                  /* ASC key if the SenseDataValid is True */
    unchar   ASCQ;                 /* ASCQ key if the SenseDataValid is True */
    unchar   SenseKey;             /* Sense key if the SenseDataValid is True */
  } SCSIPassThrough, *PSCSIPassThrough;
  #define SCSI_DATA_OUT  1
  #define SCSI_DATA_IN   2
  #define SCSI_DATA_NONE 3

SCSI_DATA_OUT indicates sending data out of the initiator (host bus adapter), also known as write mode. SCSI_DATA_IN indicates receiving data into the initiator (host bus adapter), also known as read mode. SCSI_DATA_NONE indicates that no data is transferred.

An example of the SCSI_PASS_THROUGH command is
#include <sys/IBM_tape.h>
SCSIPassThrough PassThrough;
memset(&PassThrough, 0, sizeof(SCSIPassThrough);
/* Issue test unit ready command */
PassThrough.CDB[0] = 0x00;
PassThrough.CommandLength = 6;
PassThrough.DataDirection = SCSI_DATA_NONE;
if (!ioctl (fd, SCSI_PASS_THROUGH, &PassThrough)) {
   printf ("The SCSI_PASS_THROUGH ioctl succeeded\n");
   if((PassThrough.TargetStatus == STATUS_SUCCESS) &&
       (PassThrough.MessageStatus == STATUS_SUCCESS) &&
       (PassThrough.HostStatus == STATUS_SUCCESS) &&
       (PassThrough.DriverStatus == STATUS_SUCCESS))
		    printf(" Test Unit Ready returns success\n");

   else {
     printf(" Test Unit Ready failed\n");
       printf("Sense Key %02x, ASC %02x, ASCQ %02x\n",
            PassThrough.SenseKey, PassThrough.ASC,
else {
   perror ("The SIOC SCSI_PASS_THROUGH ioctl failed");