BOOLEAN VioScsiBuildIo( IN PVOID DeviceExtension, IN PSCSI_REQUEST_BLOCK Srb ) { PCDB cdb; ULONG i; ULONG fragLen; ULONG sgElement; ULONG sgMaxElements; PADAPTER_EXTENSION adaptExt; PSRB_EXTENSION srbExt; PSTOR_SCATTER_GATHER_LIST sgList; VirtIOSCSICmd *cmd; ENTER_FN(); cdb = (PCDB)&Srb->Cdb[0]; srbExt = (PSRB_EXTENSION)Srb->SrbExtension; adaptExt = (PADAPTER_EXTENSION)DeviceExtension; if( (Srb->PathId > 0) || (Srb->TargetId >= adaptExt->scsi_config.max_target) || (Srb->Lun >= adaptExt->scsi_config.max_lun) ) { Srb->SrbStatus = SRB_STATUS_NO_DEVICE; StorPortNotification(RequestComplete, DeviceExtension, Srb); return FALSE; } RhelDbgPrint(TRACE_LEVEL_VERBOSE, ("<-->%s (%d::%d::%d)\n", DbgGetScsiOpStr(Srb), Srb->PathId, Srb->TargetId, Srb->Lun)); memset(srbExt, 0, sizeof(*srbExt)); cmd = &srbExt->cmd; cmd->sc = Srb; cmd->req.cmd.lun[0] = 1; cmd->req.cmd.lun[1] = Srb->TargetId; cmd->req.cmd.lun[2] = 0; cmd->req.cmd.lun[3] = Srb->Lun; cmd->req.cmd.tag = (unsigned long)Srb; cmd->req.cmd.task_attr = VIRTIO_SCSI_S_SIMPLE; cmd->req.cmd.prio = 0; cmd->req.cmd.crn = 0; memcpy(cmd->req.cmd.cdb, cdb, min(VIRTIO_SCSI_CDB_SIZE, Srb->CdbLength)); sgElement = 0; srbExt->sg[sgElement].physAddr = StorPortGetPhysicalAddress(DeviceExtension, NULL, &cmd->req.cmd, &fragLen); srbExt->sg[sgElement].ulSize = sizeof(cmd->req.cmd); sgElement++; sgList = StorPortGetScatterGatherList(DeviceExtension, Srb); if (sgList) { sgMaxElements = sgList->NumberOfElements; if((Srb->SrbFlags & SRB_FLAGS_DATA_OUT) == SRB_FLAGS_DATA_OUT) { for (i = 0; i < sgMaxElements; i++, sgElement++) { srbExt->sg[sgElement].physAddr = sgList->List[i].PhysicalAddress; srbExt->sg[sgElement].ulSize = sgList->List[i].Length; srbExt->Xfer += sgList->List[i].Length; } } } srbExt->out = sgElement; srbExt->sg[sgElement].physAddr = StorPortGetPhysicalAddress(DeviceExtension, NULL, &cmd->resp.cmd, &fragLen); srbExt->sg[sgElement].ulSize = sizeof(cmd->resp.cmd); sgElement++; if (sgList) { sgMaxElements = sgList->NumberOfElements; if((Srb->SrbFlags & SRB_FLAGS_DATA_OUT) != SRB_FLAGS_DATA_OUT) { for (i = 0; i < sgMaxElements; i++, sgElement++) { srbExt->sg[sgElement].physAddr = sgList->List[i].PhysicalAddress; srbExt->sg[sgElement].ulSize = sgList->List[i].Length; srbExt->Xfer += sgList->List[i].Length; } } } srbExt->in = sgElement - srbExt->out; EXIT_FN(); 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; }