BOOLEAN RhelDoReadWrite(PVOID DeviceExtension, PSCSI_REQUEST_BLOCK Srb) { PCDB cdb; ULONG fragLen; ULONG sgElement; ULONG BytesLeft; PVOID DataBuffer; PADAPTER_EXTENSION adaptExt; PRHEL_SRB_EXTENSION srbExt; int num_free; PVOID va; ULONGLONG pa; ULONG i; ULONG sgMaxElements; cdb = (PCDB)&Srb->Cdb[0]; srbExt = (PRHEL_SRB_EXTENSION)Srb->SrbExtension; adaptExt = (PADAPTER_EXTENSION)DeviceExtension; BytesLeft= Srb->DataTransferLength; DataBuffer = Srb->DataBuffer; memset(srbExt, 0, sizeof (RHEL_SRB_EXTENSION)); sgMaxElements = MAX_PHYS_SEGMENTS + 1; for (i = 0, sgElement = 1; (i < sgMaxElements) && BytesLeft; i++, sgElement++) { srbExt->vbr.sg[sgElement].physAddr = ScsiPortGetPhysicalAddress(DeviceExtension, Srb, DataBuffer, &fragLen); srbExt->vbr.sg[sgElement].ulSize = fragLen; srbExt->Xfer += fragLen; BytesLeft -= fragLen; DataBuffer = (PVOID)((ULONG_PTR)DataBuffer + fragLen); } srbExt->vbr.out_hdr.sector = RhelGetLba(DeviceExtension, cdb); srbExt->vbr.out_hdr.ioprio = 0; srbExt->vbr.req = (struct request *)Srb; if (Srb->SrbFlags & SRB_FLAGS_DATA_OUT) { srbExt->vbr.out_hdr.type = VIRTIO_BLK_T_OUT; srbExt->out = sgElement; srbExt->in = 1; } else { srbExt->vbr.out_hdr.type = VIRTIO_BLK_T_IN; srbExt->out = 1; srbExt->in = sgElement; } srbExt->vbr.sg[0].physAddr = ScsiPortGetPhysicalAddress(DeviceExtension, NULL, &srbExt->vbr.out_hdr, &fragLen); srbExt->vbr.sg[0].ulSize = sizeof(srbExt->vbr.out_hdr); srbExt->vbr.sg[sgElement].physAddr = ScsiPortGetPhysicalAddress(DeviceExtension, NULL, &srbExt->vbr.status, &fragLen); srbExt->vbr.sg[sgElement].ulSize = sizeof(srbExt->vbr.status); SET_VA_PA(); num_free = adaptExt->vq->vq_ops->add_buf(adaptExt->vq, &srbExt->vbr.sg[0], srbExt->out, srbExt->in, &srbExt->vbr, va, pa); if ( num_free >= 0) { InsertTailList(&adaptExt->list_head, &srbExt->vbr.list_entry); adaptExt->vq->vq_ops->kick(adaptExt->vq); srbExt->call_next = FALSE; if(!adaptExt->indirect && num_free < VIRTIO_MAX_SG) { srbExt->call_next = TRUE; } else { ScsiPortNotification(NextLuRequest, DeviceExtension, Srb->PathId, Srb->TargetId, Srb->Lun); } } return TRUE; }
BOOLEAN VirtIoBuildIo( IN PVOID DeviceExtension, IN PSCSI_REQUEST_BLOCK Srb ) { PCDB cdb; ULONG i; ULONG dummy; ULONG sgElement; ULONG sgMaxElements; PADAPTER_EXTENSION adaptExt; PRHEL_SRB_EXTENSION srbExt; PSTOR_SCATTER_GATHER_LIST sgList; cdb = (PCDB)&Srb->Cdb[0]; srbExt = (PRHEL_SRB_EXTENSION)Srb->SrbExtension; adaptExt = (PADAPTER_EXTENSION)DeviceExtension; if(Srb->PathId || Srb->TargetId || Srb->Lun) { Srb->SrbStatus = SRB_STATUS_NO_DEVICE; ScsiPortNotification(RequestComplete, DeviceExtension, Srb); return FALSE; } switch (cdb->CDB6GENERIC.OperationCode) { case SCSIOP_READ: case SCSIOP_WRITE: case SCSIOP_WRITE_VERIFY: case SCSIOP_READ6: case SCSIOP_WRITE6: case SCSIOP_READ12: case SCSIOP_WRITE12: case SCSIOP_WRITE_VERIFY12: case SCSIOP_READ16: case SCSIOP_WRITE16: case SCSIOP_WRITE_VERIFY16: { break; } default: { Srb->SrbStatus = SRB_STATUS_SUCCESS; return TRUE; } } sgList = StorPortGetScatterGatherList(DeviceExtension, Srb); sgMaxElements = min((MAX_PHYS_SEGMENTS + 1), sgList->NumberOfElements); srbExt->Xfer = 0; for (i = 0, sgElement = 1; i < sgMaxElements; i++, sgElement++) { srbExt->vbr.sg[sgElement].physAddr = sgList->List[i].PhysicalAddress; srbExt->vbr.sg[sgElement].ulSize = sgList->List[i].Length; srbExt->Xfer += sgList->List[i].Length; } srbExt->vbr.out_hdr.sector = RhelGetLba(DeviceExtension, cdb); srbExt->vbr.out_hdr.ioprio = 0; srbExt->vbr.req = (PVOID)Srb; srbExt->fua = (cdb->CDB10.ForceUnitAccess == 1); if (Srb->SrbFlags & SRB_FLAGS_DATA_OUT) { srbExt->vbr.out_hdr.type = VIRTIO_BLK_T_OUT; srbExt->out = sgElement; srbExt->in = 1; } else { srbExt->vbr.out_hdr.type = VIRTIO_BLK_T_IN; srbExt->out = 1; srbExt->in = sgElement; } srbExt->vbr.sg[0].physAddr = ScsiPortGetPhysicalAddress(DeviceExtension, NULL, &srbExt->vbr.out_hdr, &dummy); srbExt->vbr.sg[0].ulSize = sizeof(srbExt->vbr.out_hdr); srbExt->vbr.sg[sgElement].physAddr = ScsiPortGetPhysicalAddress(DeviceExtension, NULL, &srbExt->vbr.status, &dummy); srbExt->vbr.sg[sgElement].ulSize = sizeof(srbExt->vbr.status); return TRUE; }
BOOLEAN VirtIoBuildIo( IN PVOID DeviceExtension, IN PSCSI_REQUEST_BLOCK Srb ) { PCDB cdb; ULONG i; ULONG dummy; ULONG sgElement; ULONG sgMaxElements; PADAPTER_EXTENSION adaptExt; PRHEL_SRB_EXTENSION srbExt; PSTOR_SCATTER_GATHER_LIST sgList; ULONGLONG lba; ULONG blocks; cdb = (PCDB)&Srb->Cdb[0]; srbExt = (PRHEL_SRB_EXTENSION)Srb->SrbExtension; adaptExt = (PADAPTER_EXTENSION)DeviceExtension; if(Srb->PathId || Srb->TargetId || Srb->Lun) { Srb->SrbStatus = SRB_STATUS_NO_DEVICE; ScsiPortNotification(RequestComplete, DeviceExtension, Srb); return FALSE; } switch (cdb->CDB6GENERIC.OperationCode) { case SCSIOP_READ: case SCSIOP_WRITE: case SCSIOP_WRITE_VERIFY: case SCSIOP_READ6: case SCSIOP_WRITE6: case SCSIOP_READ12: case SCSIOP_WRITE12: case SCSIOP_WRITE_VERIFY12: case SCSIOP_READ16: case SCSIOP_WRITE16: case SCSIOP_WRITE_VERIFY16: { break; } default: { Srb->SrbStatus = SRB_STATUS_SUCCESS; return TRUE; } } lba = RhelGetLba(DeviceExtension, cdb); blocks = (Srb->DataTransferLength + adaptExt->info.blk_size - 1) / adaptExt->info.blk_size; if (lba > adaptExt->lastLBA) { RhelDbgPrint(TRACE_LEVEL_ERROR, ("SRB_STATUS_BAD_SRB_BLOCK_LENGTH lba = %llu lastLBA= %llu\n", lba, adaptExt->lastLBA)); Srb->SrbStatus = SRB_STATUS_BAD_SRB_BLOCK_LENGTH; CompleteSRB(DeviceExtension, Srb); return FALSE; } if ((lba + blocks) > adaptExt->lastLBA) { blocks = (ULONG)(adaptExt->lastLBA + 1 - lba); RhelDbgPrint(TRACE_LEVEL_ERROR, ("lba = %llu lastLBA= %llu blocks = %lu\n", lba, adaptExt->lastLBA, blocks)); Srb->DataTransferLength = (ULONG)(blocks * adaptExt->info.blk_size); } sgList = StorPortGetScatterGatherList(DeviceExtension, Srb); sgMaxElements = min((MAX_PHYS_SEGMENTS + 1), sgList->NumberOfElements); srbExt->Xfer = 0; for (i = 0, sgElement = 1; i < sgMaxElements; i++, sgElement++) { srbExt->vbr.sg[sgElement].physAddr = sgList->List[i].PhysicalAddress; srbExt->vbr.sg[sgElement].length = sgList->List[i].Length; srbExt->Xfer += sgList->List[i].Length; } srbExt->vbr.out_hdr.sector = lba; srbExt->vbr.out_hdr.ioprio = 0; srbExt->vbr.req = (PVOID)Srb; srbExt->fua = (cdb->CDB10.ForceUnitAccess == 1); if (Srb->SrbFlags & SRB_FLAGS_DATA_OUT) { srbExt->vbr.out_hdr.type = VIRTIO_BLK_T_OUT; srbExt->out = sgElement; srbExt->in = 1; } else { srbExt->vbr.out_hdr.type = VIRTIO_BLK_T_IN; srbExt->out = 1; srbExt->in = sgElement; } srbExt->vbr.sg[0].physAddr = ScsiPortGetPhysicalAddress(DeviceExtension, NULL, &srbExt->vbr.out_hdr, &dummy); srbExt->vbr.sg[0].length = sizeof(srbExt->vbr.out_hdr); srbExt->vbr.sg[sgElement].physAddr = ScsiPortGetPhysicalAddress(DeviceExtension, NULL, &srbExt->vbr.status, &dummy); srbExt->vbr.sg[sgElement].length = sizeof(srbExt->vbr.status); return TRUE; }