static int mptsas_process_scsi_io_request(MPTSASState *s, MPIMsgSCSIIORequest *scsi_io, hwaddr addr) { MPTSASRequest *req; MPIMsgSCSIIOReply reply; SCSIDevice *sdev; int status; mptsas_fix_scsi_io_endianness(scsi_io); trace_mptsas_process_scsi_io_request(s, scsi_io->Bus, scsi_io->TargetID, scsi_io->LUN[1], scsi_io->DataLength); status = mptsas_scsi_device_find(s, scsi_io->Bus, scsi_io->TargetID, scsi_io->LUN, &sdev); if (status) { goto bad; } req = g_new(MPTSASRequest, 1); QTAILQ_INSERT_TAIL(&s->pending, req, next); req->scsi_io = *scsi_io; req->dev = s; status = mptsas_build_sgl(s, req, addr); if (status) { goto free_bad; } if (req->qsg.size < scsi_io->DataLength) { trace_mptsas_sgl_overflow(s, scsi_io->MsgContext, scsi_io->DataLength, req->qsg.size); status = MPI_IOCSTATUS_INVALID_SGL; goto free_bad; } req->sreq = scsi_req_new(sdev, scsi_io->MsgContext, scsi_io->LUN[1], scsi_io->CDB, req); if (req->sreq->cmd.xfer > scsi_io->DataLength) { goto overrun; } switch (scsi_io->Control & MPI_SCSIIO_CONTROL_DATADIRECTION_MASK) { case MPI_SCSIIO_CONTROL_NODATATRANSFER: if (req->sreq->cmd.mode != SCSI_XFER_NONE) { goto overrun; } break; case MPI_SCSIIO_CONTROL_WRITE: if (req->sreq->cmd.mode != SCSI_XFER_TO_DEV) { goto overrun; } break; case MPI_SCSIIO_CONTROL_READ: if (req->sreq->cmd.mode != SCSI_XFER_FROM_DEV) { goto overrun; } break; } if (scsi_req_enqueue(req->sreq)) { scsi_req_continue(req->sreq); } return 0; overrun: trace_mptsas_scsi_overflow(s, scsi_io->MsgContext, req->sreq->cmd.xfer, scsi_io->DataLength); status = MPI_IOCSTATUS_SCSI_DATA_OVERRUN; free_bad: mptsas_free_request(req); bad: memset(&reply, 0, sizeof(reply)); reply.TargetID = scsi_io->TargetID; reply.Bus = scsi_io->Bus; reply.MsgLength = sizeof(reply) / 4; reply.Function = scsi_io->Function; reply.CDBLength = scsi_io->CDBLength; reply.SenseBufferLength = scsi_io->SenseBufferLength; reply.MsgContext = scsi_io->MsgContext; reply.SCSIState = MPI_SCSI_STATE_NO_SCSI_STATUS; reply.IOCStatus = status; mptsas_fix_scsi_io_reply_endianness(&reply); mptsas_reply(s, (MPIDefaultReply *)&reply); return 0; }
static int mptsas_process_scsi_io_request(MPTSASState *s, MPIMsgSCSIIORequest *scsi_io, hwaddr addr) { MPTSASRequest *req; MPIMsgSCSIIOReply reply; SCSIDevice *sdev; int status; mptsas_fix_scsi_io_endianness(scsi_io); trace_mptsas_process_scsi_io_request(s, scsi_io->Bus, scsi_io->TargetID, scsi_io->LUN[1], scsi_io->DataLength); status = mptsas_scsi_device_find(s, scsi_io->Bus, scsi_io->TargetID, scsi_io->LUN, &sdev); if (status) { goto bad; } req = g_new(MPTSASRequest, 1); QTAILQ_INSERT_TAIL(&s->pending, req, next); req->scsi_io = *scsi_io; req->dev = s; status = mptsas_build_sgl(s, req, addr); if (status) { goto free_bad; } if (req->qsg.size < scsi_io->DataLength) { trace_mptsas_sgl_overflow(s, scsi_io->MsgContext, scsi_io->DataLength, req->qsg.size); status = MPI_IOCSTATUS_INVALID_SGL; goto free_bad; } req->sreq = scsi_req_new(sdev, scsi_io->MsgContext, scsi_io->LUN[1], scsi_io->CDB, req); if (req->sreq->cmd.xfer > scsi_io->DataLength) { goto overrun; } switch (scsi_io->Control & MPI_SCSIIO_CONTROL_DATADIRECTION_MASK) { case MPI_SCSIIO_CONTROL_NODATATRANSFER: if (req->sreq->cmd.mode != SCSI_XFER_NONE) { goto overrun; } break; case MPI_SCSIIO_CONTROL_WRITE: if (req->sreq->cmd.mode != SCSI_XFER_TO_DEV) { goto overrun; } break; case MPI_SCSIIO_CONTROL_READ: if (req->sreq->cmd.mode != SCSI_XFER_FROM_DEV) { goto overrun; } break; } if (scsi_req_enqueue(req->sreq)) { scsi_req_continue(req->sreq); } return 0; overrun: trace_mptsas_scsi_overflow(s, scsi_io->MsgContext, req->sreq->cmd.xfer, scsi_io->DataLength); status = MPI_IOCSTATUS_SCSI_DATA_OVERRUN; free_bad: mptsas_free_request(req); bad: memset(&reply, 0, sizeof(reply)); reply.TargetID = scsi_io->TargetID; reply.Bus = scsi_io->Bus; reply.MsgLength = sizeof(reply) / 4; reply.Function = scsi_io->Function; reply.CDBLength = scsi_io->CDBLength; reply.SenseBufferLength = scsi_io->SenseBufferLength; reply.MsgContext = scsi_io->MsgContext; reply.SCSIState = MPI_SCSI_STATE_NO_SCSI_STATUS; reply.IOCStatus = status; mptsas_fix_scsi_io_reply_endianness(&reply); mptsas_reply(s, (MPIDefaultReply *)&reply); return 0; }