static void mptsas_process_scsi_task_mgmt(MPTSASState *s, MPIMsgSCSITaskMgmt *req)

{

    MPIMsgSCSITaskMgmtReply reply;

    MPIMsgSCSITaskMgmtReply *reply_async;

    int status, count;

    SCSIDevice *sdev;

    SCSIRequest *r, *next;

    BusChild *kid;



    mptsas_fix_scsi_task_mgmt_endianness(req);



    QEMU_BUILD_BUG_ON(MPTSAS_MAX_REQUEST_SIZE < sizeof(*req));

    QEMU_BUILD_BUG_ON(sizeof(s->doorbell_msg) < sizeof(*req));

    QEMU_BUILD_BUG_ON(sizeof(s->doorbell_reply) < sizeof(reply));



    memset(&reply, 0, sizeof(reply));

    reply.TargetID   = req->TargetID;

    reply.Bus        = req->Bus;

    reply.MsgLength  = sizeof(reply) / 4;

    reply.Function   = req->Function;

    reply.TaskType   = req->TaskType;

    reply.MsgContext = req->MsgContext;



    switch (req->TaskType) {

    case MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK:

    case MPI_SCSITASKMGMT_TASKTYPE_QUERY_TASK:

        status = mptsas_scsi_device_find(s, req->Bus, req->TargetID,

                                         req->LUN, &sdev);

        if (status) {

            reply.IOCStatus = status;

            goto out;

        }

        if (sdev->lun != req->LUN[1]) {

            reply.ResponseCode = MPI_SCSITASKMGMT_RSP_TM_INVALID_LUN;

            goto out;

        }



        QTAILQ_FOREACH_SAFE(r, &sdev->requests, next, next) {

            MPTSASRequest *cmd_req = r->hba_private;

            if (cmd_req && cmd_req->scsi_io.MsgContext == req->TaskMsgContext) {

                break;

            }

        }

        if (r) {

            /*

             * Assert that the request has not been completed yet, we

             * check for it in the loop above.

             */

            assert(r->hba_private);

            if (req->TaskType == MPI_SCSITASKMGMT_TASKTYPE_QUERY_TASK) {

                /* "If the specified command is present in the task set, then

                 * return a service response set to FUNCTION SUCCEEDED".

                 */

                reply.ResponseCode = MPI_SCSITASKMGMT_RSP_TM_SUCCEEDED;

            } else {

                MPTSASCancelNotifier *notifier;



                reply_async = g_memdup(&reply, sizeof(MPIMsgSCSITaskMgmtReply));

                reply_async->IOCLogInfo = INT_MAX;



                count = 1;

                notifier = g_new(MPTSASCancelNotifier, 1);

                notifier->s = s;

                notifier->reply = reply_async;

                notifier->notifier.notify = mptsas_cancel_notify;

                scsi_req_cancel_async(r, &notifier->notifier);

                goto reply_maybe_async;

            }

        }

        break;



    case MPI_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET:

    case MPI_SCSITASKMGMT_TASKTYPE_CLEAR_TASK_SET:

        status = mptsas_scsi_device_find(s, req->Bus, req->TargetID,

                                         req->LUN, &sdev);

        if (status) {

            reply.IOCStatus = status;

            goto out;

        }

        if (sdev->lun != req->LUN[1]) {

            reply.ResponseCode = MPI_SCSITASKMGMT_RSP_TM_INVALID_LUN;

            goto out;

        }



        reply_async = g_memdup(&reply, sizeof(MPIMsgSCSITaskMgmtReply));

        reply_async->IOCLogInfo = INT_MAX;



        count = 0;

        QTAILQ_FOREACH_SAFE(r, &sdev->requests, next, next) {

            if (r->hba_private) {

                MPTSASCancelNotifier *notifier;



                count++;

                notifier = g_new(MPTSASCancelNotifier, 1);

                notifier->s = s;

                notifier->reply = reply_async;

                notifier->notifier.notify = mptsas_cancel_notify;

                scsi_req_cancel_async(r, &notifier->notifier);

            }

        }



reply_maybe_async:

        if (reply_async->TerminationCount < count) {

            reply_async->IOCLogInfo = count;

            return;

        }


        reply.TerminationCount = count;

        break;



    case MPI_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET:

        status = mptsas_scsi_device_find(s, req->Bus, req->TargetID,

                                         req->LUN, &sdev);

        if (status) {

            reply.IOCStatus = status;

            goto out;

        }

        if (sdev->lun != req->LUN[1]) {

            reply.ResponseCode = MPI_SCSITASKMGMT_RSP_TM_INVALID_LUN;

            goto out;

        }

        qdev_reset_all(&sdev->qdev);

        break;



    case MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET:

        if (req->Bus != 0) {

            reply.IOCStatus = MPI_IOCSTATUS_SCSI_INVALID_BUS;

            goto out;

        }

        if (req->TargetID > s->max_devices) {

            reply.IOCStatus = MPI_IOCSTATUS_SCSI_INVALID_TARGETID;

            goto out;

        }



        QTAILQ_FOREACH(kid, &s->bus.qbus.children, sibling) {

            sdev = SCSI_DEVICE(kid->child);

            if (sdev->channel == 0 && sdev->id == req->TargetID) {

                qdev_reset_all(kid->child);

            }

        }

        break;



    case MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS:

        qbus_reset_all(&s->bus.qbus);

        break;



    default:

        reply.ResponseCode = MPI_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED;

        break;

    }



out:

    mptsas_fix_scsi_task_mgmt_reply_endianness(&reply);

    mptsas_post_reply(s, (MPIDefaultReply *)&reply);

}
static void mptsas_process_scsi_task_mgmt(MPTSASState *s, MPIMsgSCSITaskMgmt *req)

{

    MPIMsgSCSITaskMgmtReply reply;

    MPIMsgSCSITaskMgmtReply *reply_async;

    int status, count;

    SCSIDevice *sdev;

    SCSIRequest *r, *next;

    BusChild *kid;



    mptsas_fix_scsi_task_mgmt_endianness(req);



    QEMU_BUILD_BUG_ON(MPTSAS_MAX_REQUEST_SIZE < sizeof(*req));

    QEMU_BUILD_BUG_ON(sizeof(s->doorbell_msg) < sizeof(*req));

    QEMU_BUILD_BUG_ON(sizeof(s->doorbell_reply) < sizeof(reply));



    memset(&reply, 0, sizeof(reply));

    reply.TargetID   = req->TargetID;

    reply.Bus        = req->Bus;

    reply.MsgLength  = sizeof(reply) / 4;

    reply.Function   = req->Function;

    reply.TaskType   = req->TaskType;

    reply.MsgContext = req->MsgContext;



    switch (req->TaskType) {

    case MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK:

    case MPI_SCSITASKMGMT_TASKTYPE_QUERY_TASK:

        status = mptsas_scsi_device_find(s, req->Bus, req->TargetID,

                                         req->LUN, &sdev);

        if (status) {

            reply.IOCStatus = status;

            goto out;

        }

        if (sdev->lun != req->LUN[1]) {

            reply.ResponseCode = MPI_SCSITASKMGMT_RSP_TM_INVALID_LUN;

            goto out;

        }



        QTAILQ_FOREACH_SAFE(r, &sdev->requests, next, next) {

            MPTSASRequest *cmd_req = r->hba_private;

            if (cmd_req && cmd_req->scsi_io.MsgContext == req->TaskMsgContext) {

                break;

            }

        }

        if (r) {

            







            assert(r->hba_private);

            if (req->TaskType == MPI_SCSITASKMGMT_TASKTYPE_QUERY_TASK) {

                





                reply.ResponseCode = MPI_SCSITASKMGMT_RSP_TM_SUCCEEDED;

            } else {

                MPTSASCancelNotifier *notifier;



                reply_async = g_memdup(&reply, sizeof(MPIMsgSCSITaskMgmtReply));

                reply_async->IOCLogInfo = INT_MAX;



                count = 1;

                notifier = g_new(MPTSASCancelNotifier, 1);

                notifier->s = s;

                notifier->reply = reply_async;

                notifier->notifier.notify = mptsas_cancel_notify;

                scsi_req_cancel_async(r, &notifier->notifier);

                goto reply_maybe_async;

            }

        }

        break;



    case MPI_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET:

    case MPI_SCSITASKMGMT_TASKTYPE_CLEAR_TASK_SET:

        status = mptsas_scsi_device_find(s, req->Bus, req->TargetID,

                                         req->LUN, &sdev);

        if (status) {

            reply.IOCStatus = status;

            goto out;

        }

        if (sdev->lun != req->LUN[1]) {

            reply.ResponseCode = MPI_SCSITASKMGMT_RSP_TM_INVALID_LUN;

            goto out;

        }



        reply_async = g_memdup(&reply, sizeof(MPIMsgSCSITaskMgmtReply));

        reply_async->IOCLogInfo = INT_MAX;



        count = 0;

        QTAILQ_FOREACH_SAFE(r, &sdev->requests, next, next) {

            if (r->hba_private) {

                MPTSASCancelNotifier *notifier;



                count++;

                notifier = g_new(MPTSASCancelNotifier, 1);

                notifier->s = s;

                notifier->reply = reply_async;

                notifier->notifier.notify = mptsas_cancel_notify;

                scsi_req_cancel_async(r, &notifier->notifier);

            }

        }



reply_maybe_async:

        if (reply_async->TerminationCount < count) {

            reply_async->IOCLogInfo = count;

            return;

        }


        reply.TerminationCount = count;

        break;



    case MPI_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET:

        status = mptsas_scsi_device_find(s, req->Bus, req->TargetID,

                                         req->LUN, &sdev);

        if (status) {

            reply.IOCStatus = status;

            goto out;

        }

        if (sdev->lun != req->LUN[1]) {

            reply.ResponseCode = MPI_SCSITASKMGMT_RSP_TM_INVALID_LUN;

            goto out;

        }

        qdev_reset_all(&sdev->qdev);

        break;



    case MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET:

        if (req->Bus != 0) {

            reply.IOCStatus = MPI_IOCSTATUS_SCSI_INVALID_BUS;

            goto out;

        }

        if (req->TargetID > s->max_devices) {

            reply.IOCStatus = MPI_IOCSTATUS_SCSI_INVALID_TARGETID;

            goto out;

        }



        QTAILQ_FOREACH(kid, &s->bus.qbus.children, sibling) {

            sdev = SCSI_DEVICE(kid->child);

            if (sdev->channel == 0 && sdev->id == req->TargetID) {

                qdev_reset_all(kid->child);

            }

        }

        break;



    case MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS:

        qbus_reset_all(&s->bus.qbus);

        break;



    default:

        reply.ResponseCode = MPI_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED;

        break;

    }



out:

    mptsas_fix_scsi_task_mgmt_reply_endianness(&reply);

    mptsas_post_reply(s, (MPIDefaultReply *)&reply);

}
static void FUNC_0(MPTSASState *VAR_0, MPIMsgSCSITaskMgmt *VAR_1)

{

    MPIMsgSCSITaskMgmtReply reply;

    MPIMsgSCSITaskMgmtReply *reply_async;

    int VAR_2, VAR_3;

    SCSIDevice *sdev;

    SCSIRequest *r, *next;

    BusChild *kid;



    mptsas_fix_scsi_task_mgmt_endianness(VAR_1);



    QEMU_BUILD_BUG_ON(MPTSAS_MAX_REQUEST_SIZE < sizeof(*VAR_1));

    QEMU_BUILD_BUG_ON(sizeof(VAR_0->doorbell_msg) < sizeof(*VAR_1));

    QEMU_BUILD_BUG_ON(sizeof(VAR_0->doorbell_reply) < sizeof(reply));



    memset(&reply, 0, sizeof(reply));

    reply.TargetID   = VAR_1->TargetID;

    reply.Bus        = VAR_1->Bus;

    reply.MsgLength  = sizeof(reply) / 4;

    reply.Function   = VAR_1->Function;

    reply.TaskType   = VAR_1->TaskType;

    reply.MsgContext = VAR_1->MsgContext;



    switch (VAR_1->TaskType) {

    case MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK:

    case MPI_SCSITASKMGMT_TASKTYPE_QUERY_TASK:

        VAR_2 = mptsas_scsi_device_find(VAR_0, VAR_1->Bus, VAR_1->TargetID,

                                         VAR_1->LUN, &sdev);

        if (VAR_2) {

            reply.IOCStatus = VAR_2;

            goto out;

        }

        if (sdev->lun != VAR_1->LUN[1]) {

            reply.ResponseCode = MPI_SCSITASKMGMT_RSP_TM_INVALID_LUN;

            goto out;

        }



        QTAILQ_FOREACH_SAFE(r, &sdev->requests, next, next) {

            MPTSASRequest *cmd_req = r->hba_private;

            if (cmd_req && cmd_req->scsi_io.MsgContext == VAR_1->TaskMsgContext) {

                break;

            }

        }

        if (r) {

            







            assert(r->hba_private);

            if (VAR_1->TaskType == MPI_SCSITASKMGMT_TASKTYPE_QUERY_TASK) {

                





                reply.ResponseCode = MPI_SCSITASKMGMT_RSP_TM_SUCCEEDED;

            } else {

                MPTSASCancelNotifier *notifier;



                reply_async = g_memdup(&reply, sizeof(MPIMsgSCSITaskMgmtReply));

                reply_async->IOCLogInfo = INT_MAX;



                VAR_3 = 1;

                notifier = g_new(MPTSASCancelNotifier, 1);

                notifier->VAR_0 = VAR_0;

                notifier->reply = reply_async;

                notifier->notifier.notify = mptsas_cancel_notify;

                scsi_req_cancel_async(r, &notifier->notifier);

                goto reply_maybe_async;

            }

        }

        break;



    case MPI_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET:

    case MPI_SCSITASKMGMT_TASKTYPE_CLEAR_TASK_SET:

        VAR_2 = mptsas_scsi_device_find(VAR_0, VAR_1->Bus, VAR_1->TargetID,

                                         VAR_1->LUN, &sdev);

        if (VAR_2) {

            reply.IOCStatus = VAR_2;

            goto out;

        }

        if (sdev->lun != VAR_1->LUN[1]) {

            reply.ResponseCode = MPI_SCSITASKMGMT_RSP_TM_INVALID_LUN;

            goto out;

        }



        reply_async = g_memdup(&reply, sizeof(MPIMsgSCSITaskMgmtReply));

        reply_async->IOCLogInfo = INT_MAX;



        VAR_3 = 0;

        QTAILQ_FOREACH_SAFE(r, &sdev->requests, next, next) {

            if (r->hba_private) {

                MPTSASCancelNotifier *notifier;



                VAR_3++;

                notifier = g_new(MPTSASCancelNotifier, 1);

                notifier->VAR_0 = VAR_0;

                notifier->reply = reply_async;

                notifier->notifier.notify = mptsas_cancel_notify;

                scsi_req_cancel_async(r, &notifier->notifier);

            }

        }



reply_maybe_async:

        if (reply_async->TerminationCount < VAR_3) {

            reply_async->IOCLogInfo = VAR_3;

            return;

        }


        reply.TerminationCount = VAR_3;

        break;



    case MPI_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET:

        VAR_2 = mptsas_scsi_device_find(VAR_0, VAR_1->Bus, VAR_1->TargetID,

                                         VAR_1->LUN, &sdev);

        if (VAR_2) {

            reply.IOCStatus = VAR_2;

            goto out;

        }

        if (sdev->lun != VAR_1->LUN[1]) {

            reply.ResponseCode = MPI_SCSITASKMGMT_RSP_TM_INVALID_LUN;

            goto out;

        }

        qdev_reset_all(&sdev->qdev);

        break;



    case MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET:

        if (VAR_1->Bus != 0) {

            reply.IOCStatus = MPI_IOCSTATUS_SCSI_INVALID_BUS;

            goto out;

        }

        if (VAR_1->TargetID > VAR_0->max_devices) {

            reply.IOCStatus = MPI_IOCSTATUS_SCSI_INVALID_TARGETID;

            goto out;

        }



        QTAILQ_FOREACH(kid, &VAR_0->bus.qbus.children, sibling) {

            sdev = SCSI_DEVICE(kid->child);

            if (sdev->channel == 0 && sdev->id == VAR_1->TargetID) {

                qdev_reset_all(kid->child);

            }

        }

        break;



    case MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS:

        qbus_reset_all(&VAR_0->bus.qbus);

        break;



    default:

        reply.ResponseCode = MPI_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED;

        break;

    }



out:

    mptsas_fix_scsi_task_mgmt_reply_endianness(&reply);

    mptsas_post_reply(VAR_0, (MPIDefaultReply *)&reply);

}
static void FUNC_0(MPTSASState *VAR_0, MPIMsgSCSITaskMgmt *VAR_1)
{ MPIMsgSCSITaskMgmtReply reply; MPIMsgSCSITaskMgmtReply *reply_async; int VAR_2, VAR_3; SCSIDevice *sdev; SCSIRequest *r, *next; BusChild *kid; mptsas_fix_scsi_task_mgmt_endianness(VAR_1); QEMU_BUILD_BUG_ON(MPTSAS_MAX_REQUEST_SIZE < sizeof(*VAR_1)); QEMU_BUILD_BUG_ON(sizeof(VAR_0->doorbell_msg) < sizeof(*VAR_1)); QEMU_BUILD_BUG_ON(sizeof(VAR_0->doorbell_reply) < sizeof(reply)); memset(&reply, 0, sizeof(reply)); reply.TargetID   = VAR_1->TargetID; reply.Bus        = VAR_1->Bus; reply.MsgLength  = sizeof(reply) / 4; reply.Function   = VAR_1->Function; reply.TaskType   = VAR_1->TaskType; reply.MsgContext = VAR_1->MsgContext; switch (VAR_1->TaskType) { case MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK:
case MPI_SCSITASKMGMT_TASKTYPE_QUERY_TASK:
VAR_2 = mptsas_scsi_device_find(VAR_0, VAR_1->Bus, VAR_1->TargetID,
VAR_1->LUN, &sdev); if (VAR_2) { reply.IOCStatus = VAR_2; goto out; } if (sdev->lun != VAR_1->LUN[1]) { reply.ResponseCode = MPI_SCSITASKMGMT_RSP_TM_INVALID_LUN; goto out; } QTAILQ_FOREACH_SAFE(r, &sdev->requests, next, next) { MPTSASRequest *cmd_req = r->hba_private; if (cmd_req && cmd_req->scsi_io.MsgContext == VAR_1->TaskMsgContext) { break; } } if (r) { assert(r->hba_private); if (VAR_1->TaskType == MPI_SCSITASKMGMT_TASKTYPE_QUERY_TASK) { reply.ResponseCode = MPI_SCSITASKMGMT_RSP_TM_SUCCEEDED; } else { MPTSASCancelNotifier *notifier; reply_async = g_memdup(&reply, sizeof(MPIMsgSCSITaskMgmtReply)); reply_async->IOCLogInfo = INT_MAX; VAR_3 = 1; notifier = g_new(MPTSASCancelNotifier, 1); notifier->VAR_0 = VAR_0; notifier->reply = reply_async; notifier->notifier.notify = mptsas_cancel_notify; scsi_req_cancel_async(r, &notifier->notifier); goto reply_maybe_async; } } break; case MPI_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET:
case MPI_SCSITASKMGMT_TASKTYPE_CLEAR_TASK_SET:
VAR_2 = mptsas_scsi_device_find(VAR_0, VAR_1->Bus, VAR_1->TargetID,
VAR_1->LUN, &sdev); if (VAR_2) { reply.IOCStatus = VAR_2; goto out; } if (sdev->lun != VAR_1->LUN[1]) { reply.ResponseCode = MPI_SCSITASKMGMT_RSP_TM_INVALID_LUN; goto out; } reply_async = g_memdup(&reply, sizeof(MPIMsgSCSITaskMgmtReply)); reply_async->IOCLogInfo = INT_MAX; VAR_3 = 0; QTAILQ_FOREACH_SAFE(r, &sdev->requests, next, next) { if (r->hba_private) { MPTSASCancelNotifier *notifier; VAR_3++; notifier = g_new(MPTSASCancelNotifier, 1); notifier->VAR_0 = VAR_0; notifier->reply = reply_async; notifier->notifier.notify = mptsas_cancel_notify; scsi_req_cancel_async(r, &notifier->notifier); } } reply_maybe_async:
if (reply_async->TerminationCount < VAR_3) { reply_async->IOCLogInfo = VAR_3; return; } reply.TerminationCount = VAR_3; break; case MPI_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET:
VAR_2 = mptsas_scsi_device_find(VAR_0, VAR_1->Bus, VAR_1->TargetID,
VAR_1->LUN, &sdev); if (VAR_2) { reply.IOCStatus = VAR_2; goto out; } if (sdev->lun != VAR_1->LUN[1]) { reply.ResponseCode = MPI_SCSITASKMGMT_RSP_TM_INVALID_LUN; goto out; } qdev_reset_all(&sdev->qdev); break; case MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
if (VAR_1->Bus != 0) { reply.IOCStatus = MPI_IOCSTATUS_SCSI_INVALID_BUS; goto out; } if (VAR_1->TargetID > VAR_0->max_devices) { reply.IOCStatus = MPI_IOCSTATUS_SCSI_INVALID_TARGETID; goto out; } QTAILQ_FOREACH(kid, &VAR_0->bus.qbus.children, sibling) { sdev = SCSI_DEVICE(kid->child); if (sdev->channel == 0 && sdev->id == VAR_1->TargetID) { qdev_reset_all(kid->child); } } break; case MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS:
qbus_reset_all(&VAR_0->bus.qbus); break; default:
reply.ResponseCode = MPI_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED; break; } out:
mptsas_fix_scsi_task_mgmt_reply_endianness(&reply); mptsas_post_reply(VAR_0, (MPIDefaultReply *)&reply); }