ntdll: Implement IOCTL_SCSI_PASS_THROUGH(_DIRECT) on Mac OS.
This commit is contained in:
parent
75f34a615b
commit
1e0cee6d3c
|
@ -83,8 +83,28 @@
|
|||
# include <IOKit/storage/IOMedia.h>
|
||||
# include <IOKit/storage/IOCDMediaBSDClient.h>
|
||||
# include <IOKit/storage/IODVDMediaBSDClient.h>
|
||||
# include <IOKit/scsi/SCSITask.h>
|
||||
# include <IOKit/scsi/SCSICmds_REQUEST_SENSE_Defs.h>
|
||||
# define SENSEBUFLEN kSenseDefaultSize
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t attribute;
|
||||
uint32_t timeout;
|
||||
uint32_t response;
|
||||
uint32_t status;
|
||||
uint8_t direction;
|
||||
uint8_t cdbSize;
|
||||
uint8_t reserved0144[2];
|
||||
uint8_t cdb[16];
|
||||
void* buffer;
|
||||
uint64_t bufferSize;
|
||||
void* sense;
|
||||
uint64_t senseLen;
|
||||
} dk_scsi_command_t;
|
||||
|
||||
#define DKIOCSCSICOMMAND _IOWR('d', 253, dk_scsi_command_t)
|
||||
|
||||
#endif
|
||||
|
||||
#define NONAMELESSUNION
|
||||
|
@ -1649,6 +1669,9 @@ static NTSTATUS CDROM_ScsiPassThroughDirect(int fd, PSCSI_PASS_THROUGH_DIRECT pP
|
|||
#elif defined HAVE_SCSIREQ_T_CMD
|
||||
scsireq_t cmd;
|
||||
int io;
|
||||
#elif defined __APPLE__
|
||||
dk_scsi_command_t cmd;
|
||||
int io;
|
||||
#endif
|
||||
|
||||
if (pPacket->Length < sizeof(SCSI_PASS_THROUGH_DIRECT))
|
||||
|
@ -1752,6 +1775,64 @@ static NTSTATUS CDROM_ScsiPassThroughDirect(int fd, PSCSI_PASS_THROUGH_DIRECT pP
|
|||
pPacket->ScsiStatus = cmd.status;
|
||||
|
||||
ret = CDROM_GetStatusCode(io);
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
memcpy(cmd.cdb, pPacket->Cdb, pPacket->CdbLength);
|
||||
|
||||
cmd.cdbSize = pPacket->CdbLength;
|
||||
cmd.buffer = pPacket->DataBuffer;
|
||||
cmd.bufferSize = pPacket->DataTransferLength;
|
||||
cmd.sense = (char*)pPacket + pPacket->SenseInfoOffset;
|
||||
cmd.senseLen = pPacket->SenseInfoLength;
|
||||
cmd.timeout = pPacket->TimeOutValue*1000; /* in milliseconds */
|
||||
|
||||
switch (pPacket->DataIn)
|
||||
{
|
||||
case SCSI_IOCTL_DATA_OUT:
|
||||
cmd.direction = kSCSIDataTransfer_FromInitiatorToTarget;
|
||||
break;
|
||||
case SCSI_IOCTL_DATA_IN:
|
||||
cmd.direction = kSCSIDataTransfer_FromTargetToInitiator;
|
||||
break;
|
||||
case SCSI_IOCTL_DATA_UNSPECIFIED:
|
||||
cmd.direction = kSCSIDataTransfer_NoDataTransfer;
|
||||
break;
|
||||
default:
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
io = ioctl(fd, DKIOCSCSICOMMAND, &cmd);
|
||||
|
||||
if (cmd.response == kSCSIServiceResponse_SERVICE_DELIVERY_OR_TARGET_FAILURE)
|
||||
{
|
||||
/* Command failed */
|
||||
switch (cmd.status)
|
||||
{
|
||||
case kSCSITaskStatus_TaskTimeoutOccurred: return STATUS_TIMEOUT;
|
||||
break;
|
||||
case kSCSITaskStatus_ProtocolTimeoutOccurred: return STATUS_IO_TIMEOUT;
|
||||
break;
|
||||
case kSCSITaskStatus_DeviceNotResponding: return STATUS_DEVICE_BUSY;
|
||||
break;
|
||||
case kSCSITaskStatus_DeviceNotPresent:
|
||||
return STATUS_NO_SUCH_DEVICE;
|
||||
break;
|
||||
case kSCSITaskStatus_DeliveryFailure:
|
||||
return STATUS_DEVICE_PROTOCOL_ERROR;
|
||||
break;
|
||||
case kSCSITaskStatus_No_Status:
|
||||
default:
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (cmd.status != kSCSITaskStatus_No_Status)
|
||||
pPacket->ScsiStatus = cmd.status;
|
||||
|
||||
ret = CDROM_GetStatusCode(io);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
@ -1770,6 +1851,9 @@ static NTSTATUS CDROM_ScsiPassThrough(int fd, PSCSI_PASS_THROUGH pPacket)
|
|||
#elif defined HAVE_SCSIREQ_T_CMD
|
||||
scsireq_t cmd;
|
||||
int io;
|
||||
#elif defined __APPLE__
|
||||
dk_scsi_command_t cmd;
|
||||
int io;
|
||||
#endif
|
||||
|
||||
if (pPacket->Length < sizeof(SCSI_PASS_THROUGH))
|
||||
|
@ -1883,6 +1967,67 @@ static NTSTATUS CDROM_ScsiPassThrough(int fd, PSCSI_PASS_THROUGH pPacket)
|
|||
pPacket->ScsiStatus = cmd.status;
|
||||
|
||||
ret = CDROM_GetStatusCode(io);
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
memcpy(cmd.cdb, pPacket->Cdb, pPacket->CdbLength);
|
||||
|
||||
cmd.cdbSize = pPacket->CdbLength;
|
||||
cmd.buffer = (char*)pPacket + pPacket->DataBufferOffset;
|
||||
cmd.bufferSize = pPacket->DataTransferLength;
|
||||
cmd.sense = (char*)pPacket + pPacket->SenseInfoOffset;
|
||||
cmd.senseLen = pPacket->SenseInfoLength;
|
||||
cmd.timeout = pPacket->TimeOutValue*1000; /* in milliseconds */
|
||||
|
||||
switch (pPacket->DataIn)
|
||||
{
|
||||
case SCSI_IOCTL_DATA_OUT:
|
||||
cmd.direction = kSCSIDataTransfer_FromInitiatorToTarget;
|
||||
break;
|
||||
case SCSI_IOCTL_DATA_IN:
|
||||
cmd.direction = kSCSIDataTransfer_FromTargetToInitiator;
|
||||
break;
|
||||
case SCSI_IOCTL_DATA_UNSPECIFIED:
|
||||
cmd.direction = kSCSIDataTransfer_NoDataTransfer;
|
||||
break;
|
||||
default:
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
io = ioctl(fd, DKIOCSCSICOMMAND, &cmd);
|
||||
|
||||
if (cmd.response == kSCSIServiceResponse_SERVICE_DELIVERY_OR_TARGET_FAILURE)
|
||||
{
|
||||
/* Command failed */
|
||||
switch (cmd.status)
|
||||
{
|
||||
case kSCSITaskStatus_TaskTimeoutOccurred:
|
||||
return STATUS_TIMEOUT;
|
||||
break;
|
||||
case kSCSITaskStatus_ProtocolTimeoutOccurred:
|
||||
return STATUS_IO_TIMEOUT;
|
||||
break;
|
||||
case kSCSITaskStatus_DeviceNotResponding:
|
||||
return STATUS_DEVICE_BUSY;
|
||||
break;
|
||||
case kSCSITaskStatus_DeviceNotPresent:
|
||||
return STATUS_NO_SUCH_DEVICE;
|
||||
break;
|
||||
case kSCSITaskStatus_DeliveryFailure:
|
||||
return STATUS_DEVICE_PROTOCOL_ERROR;
|
||||
break;
|
||||
case kSCSITaskStatus_No_Status:
|
||||
default:
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (cmd.status != kSCSITaskStatus_No_Status)
|
||||
pPacket->ScsiStatus = cmd.status;
|
||||
|
||||
ret = CDROM_GetStatusCode(io);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue