Now I am trying to write an IOUserSCSIParallelInterfaceController driver which uses neither DMA nor PCI and emulates a SCSI target.
I realized that fBufferIOVMAddr ( https://developer.apple.com/documentation/scsicontrollerdriverkit/scsiuserparalleltask/3555105-fbufferiovmaddr ) in SCSIUserParallelTask struct given via UserProcessParallelTask method indicates a physical address and it couldn't be used as a memory address in the driver's memory space.
I need my driver to write something to the buffer and read something from the buffer because I want to make a SCSI Communication by my driver codes.
Is there any way to access memory in physical address from a DriverKit driver?
-
I hope UserGetDataBuffer ( developer.apple.com/documentation/scsicontrollerdriverkit/… ) method can be what helps me, but I'm not sure of that because there is no description so far.yuuzi41– yuuzi412021年07月11日 03:33:43 +00:00Commented Jul 11, 2021 at 3:33
2 Answers 2
#if ARCMSR_DEBUG_UserGetDataBuffer
if(pCCB->arcmsr_request.Cdb[0]==0xA0)/*SCSI_CMD_REPORT_LUN*/
{
IOBufferMemoryDescriptor *osdatabuffer = nullptr;
uint64_t address, len, length=pCCB->request_transfer_count; /* parallelTask.fRequestedTransferCount */
/*
******************************************************************************************************************************************
**
** virtual kern_return_t UserGetDataBuffer(SCSIDeviceIdentifier fTargetID, uint64_t fControllerTaskIdentifier, IOBufferMemoryDescriptor **osdatabuffer);
**
******************************************************************************************************************************************
*/
if((UserGetDataBuffer(fTargetID, pCCB->fControllerTaskIdentifier, &osdatabuffer) != kIOReturnSuccess) || (osdatabuffer == NULL))
{
arcmsr_debug_print("ArcMSRUserSpaceDriver %d: ************************************************************************************ \n",ivars->adapter_index);
arcmsr_debug_print("ArcMSRUserSpaceDriver %d: ** Get task data buffer error, ftargetID=%d fControllerTaskIdentifier=%d \n",ivars->adapter_index,(int)fTargetID,(int)pCCB->fControllerTaskIdentifier);
arcmsr_debug_print("ArcMSRUserSpaceDriver %d: ************************************************************************************ \n",ivars->adapter_index);
goto command_completion;
}
if((osdatabuffer->Map(0, 0, 0, 0, &address, &len) != kIOReturnSuccess) || (length != len))
{
arcmsr_debug_print("ArcMSRUserSpaceDriver %d: ************************************************************************************ \n",ivars->adapter_index);
arcmsr_debug_print("ArcMSRUserSpaceDriver %d: ** Map task data buffer error, ftargetID=%d fControllerTaskIdentifier=%d \n",ivars->adapter_index,(int)fTargetID,(int)pCCB->fControllerTaskIdentifier);
arcmsr_debug_print("ArcMSRUserSpaceDriver %d: ************************************************************************************ \n",ivars->adapter_index);
goto command_completion;
}
/*
*******************************************************************************************************************
** The LUN LIST LENGTH field shall contain the length in bytes of the LUN list that is available to be transferred.
** The LUN list length is the number of logical unit numbers in the logical unit inventory multiplied by eight.
*******************************************************************************************************************
*/
memset((void *)(address+3),8,1); /* report_lun_data */
memset((void *)(address+8),0,8); /* first lun */
response.fBytesTransferred = 16;
}
#endif
3 Comments
kern_return_t ArcNVMeUserSpaceDriver::arcnvme_parallelTask_remap_os_data_buffer(SCSIUserParallelTask *pParallelTask, PCCB pCCB)
{
IOBufferMemoryDescriptor* data_buffer_memory_descriptor = nullptr;
if ((UserGetDataBuffer(pParallelTask->fTargetID, pParallelTask->fControllerTaskIdentifier, &data_buffer_memory_descriptor) == kIOReturnSuccess) && (data_buffer_memory_descriptor != NULL))
{
IOAddressSegment data_buffer_virtual_address_segment = { 0 };
if (data_buffer_memory_descriptor->GetAddressRange(&data_buffer_virtual_address_segment) == kIOReturnSuccess)
{
IOAddressSegment data_buffer_physical_address_segment = { 0 };
IODMACommandSpecification dmaSpecification;
IODMACommand* data_buffer_iodmacommand = { 0 };
bzero(&dmaSpecification, sizeof(dmaSpecification));
dmaSpecification.options = kIODMACommandSpecificationNoOptions;
dmaSpecification.maxAddressBits = 64;
if (IODMACommand::Create(ivars->pciDevice, kIODMACommandCreateNoOptions, &dmaSpecification, &data_buffer_iodmacommand) == kIOReturnSuccess)
{
uint64_t dmaFlags = kIOMemoryDirectionInOut;
uint32_t dmaSegmentCount = 1;
pCCB->data_buffer_iodmacommand = data_buffer_iodmacommand;
if (data_buffer_iodmacommand->PrepareForDMA(kIODMACommandPrepareForDMANoOptions, data_buffer_memory_descriptor, 0/*offset*/, pParallelTask->fRequestedTransferCount/*length*/, &dmaFlags, &dmaSegmentCount, &data_buffer_physical_address_segment) == kIOReturnSuccess)
{
pParallelTask->fBufferIOVMAddr = (uint64_t)data_buffer_physical_address_segment.address; /* data_buffer_physical_address: overwrite original fBufferIOVMAddr */
pCCB->OSDataBuffer = reinterpret_cast <uint8_t*> (data_buffer_virtual_address_segment.address);/* data_buffer_virtual_address */
}
else
{
return (kIOReturnError);
}
}
else
{
return (kIOReturnError);
}
}
else
{
return (kIOReturnError);
}
}
else
{
return (kIOReturnError);
}
return(kIOReturnSuccess);
}