BOOLEAN DeviceReset( IN PVOID DeviceExtension ) { PADAPTER_EXTENSION adaptExt = (PADAPTER_EXTENSION)DeviceExtension; PSCSI_REQUEST_BLOCK Srb = &adaptExt->tmf_cmd.Srb; PSRB_EXTENSION srbExt = adaptExt->tmf_cmd.SrbExtension; VirtIOSCSICmd *cmd = &srbExt->cmd; ULONG fragLen; ULONG sgElement; ENTER_FN(); if (adaptExt->dump_mode) { return TRUE; } ASSERT(adaptExt->tmf_infly == FALSE); Srb->SrbExtension = srbExt; RtlZeroMemory((PVOID)cmd, sizeof(VirtIOSCSICmd)); cmd->sc = Srb; cmd->req.tmf.lun[0] = 1; cmd->req.tmf.lun[1] = 0; cmd->req.tmf.lun[2] = 0; cmd->req.tmf.lun[3] = 0; cmd->req.tmf.type = VIRTIO_SCSI_T_TMF; cmd->req.tmf.subtype = VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET; sgElement = 0; srbExt->sg[sgElement].physAddr = StorPortGetPhysicalAddress(DeviceExtension, NULL, &cmd->req.tmf, &fragLen); srbExt->sg[sgElement].length = sizeof(cmd->req.tmf); sgElement++; srbExt->out = sgElement; srbExt->sg[sgElement].physAddr = StorPortGetPhysicalAddress(DeviceExtension, NULL, &cmd->resp.tmf, &fragLen); srbExt->sg[sgElement].length = sizeof(cmd->resp.tmf); sgElement++; srbExt->in = sgElement - srbExt->out; StorPortPause(DeviceExtension, 60); if (!SendTMF(DeviceExtension, Srb)) { StorPortResume(DeviceExtension); return FALSE; } adaptExt->tmf_infly = TRUE; return TRUE; }
BOOLEAN VioScsiMSInterrupt ( IN PVOID DeviceExtension, IN ULONG MessageID ) { PVirtIOSCSICmd cmd; PVirtIOSCSIEventNode evtNode; unsigned int len; PADAPTER_EXTENSION adaptExt; BOOLEAN isInterruptServiced = FALSE; PSCSI_REQUEST_BLOCK Srb; PSRB_EXTENSION srbExt; ULONG intReason = 0; adaptExt = (PADAPTER_EXTENSION)DeviceExtension; RhelDbgPrint(TRACE_LEVEL_VERBOSE, ("<--->%s : MessageID 0x%x\n", __FUNCTION__, MessageID)); if (MessageID == 0) { return TRUE; } if (MessageID == 1) { if (adaptExt->tmf_infly) { while((cmd = (PVirtIOSCSICmd)adaptExt->vq[0]->vq_ops->get_buf(adaptExt->vq[0], &len)) != NULL) { VirtIOSCSICtrlTMFResp *resp; Srb = (PSCSI_REQUEST_BLOCK)cmd->sc; ASSERT(Srb == &adaptExt->tmf_cmd.Srb); resp = &cmd->resp.tmf; switch(resp->response) { case VIRTIO_SCSI_S_OK: case VIRTIO_SCSI_S_FUNCTION_SUCCEEDED: break; default: RhelDbgPrint(TRACE_LEVEL_ERROR, ("Unknown response %d\n", resp->response)); ASSERT(0); break; } StorPortResume(DeviceExtension); } adaptExt->tmf_infly = FALSE; } return TRUE; } if (MessageID == 2) { while((evtNode = (PVirtIOSCSIEventNode)adaptExt->vq[1]->vq_ops->get_buf(adaptExt->vq[1], &len)) != NULL) { PVirtIOSCSIEvent evt = &evtNode->event; switch (evt->event) { case VIRTIO_SCSI_T_NO_EVENT: break; case VIRTIO_SCSI_T_TRANSPORT_RESET: TransportReset(DeviceExtension, evt); break; case VIRTIO_SCSI_T_PARAM_CHANGE: ParamChange(DeviceExtension, evt); break; default: RhelDbgPrint(TRACE_LEVEL_ERROR, ("Unsupport virtio scsi event %x\n", evt->event)); break; } SynchronizedKickEventRoutine(DeviceExtension, evtNode); } return TRUE; } if (MessageID == 3) { while((cmd = (PVirtIOSCSICmd)adaptExt->vq[2]->vq_ops->get_buf(adaptExt->vq[2], &len)) != NULL) { VirtIOSCSICmdResp *resp; Srb = (PSCSI_REQUEST_BLOCK)cmd->sc; resp = &cmd->resp.cmd; srbExt = (PSRB_EXTENSION)Srb->SrbExtension; switch (resp->response) { case VIRTIO_SCSI_S_OK: Srb->ScsiStatus = resp->status; Srb->SrbStatus = (Srb->ScsiStatus == SCSISTAT_GOOD) ? SRB_STATUS_SUCCESS : SRB_STATUS_ERROR; break; case VIRTIO_SCSI_S_UNDERRUN: RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("VIRTIO_SCSI_S_UNDERRUN\n")); Srb->SrbStatus = SRB_STATUS_DATA_OVERRUN; break; case VIRTIO_SCSI_S_ABORTED: RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("VIRTIO_SCSI_S_ABORTED\n")); Srb->SrbStatus = SRB_STATUS_ABORTED; break; case VIRTIO_SCSI_S_BAD_TARGET: RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("VIRTIO_SCSI_S_BAD_TARGET\n")); Srb->SrbStatus = SRB_STATUS_INVALID_TARGET_ID; break; case VIRTIO_SCSI_S_RESET: RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("VIRTIO_SCSI_S_RESET\n")); Srb->SrbStatus = SRB_STATUS_BUS_RESET; break; case VIRTIO_SCSI_S_BUSY: RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("VIRTIO_SCSI_S_BUSY\n")); Srb->SrbStatus = SRB_STATUS_BUSY; break; case VIRTIO_SCSI_S_TRANSPORT_FAILURE: RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("VIRTIO_SCSI_S_TRANSPORT_FAILURE\n")); Srb->SrbStatus = SRB_STATUS_ERROR; break; case VIRTIO_SCSI_S_TARGET_FAILURE: RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("VIRTIO_SCSI_S_TARGET_FAILURE\n")); Srb->SrbStatus = SRB_STATUS_ERROR; break; case VIRTIO_SCSI_S_NEXUS_FAILURE: RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("VIRTIO_SCSI_S_NEXUS_FAILURE\n")); Srb->SrbStatus = SRB_STATUS_ERROR; break; case VIRTIO_SCSI_S_FAILURE: RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("VIRTIO_SCSI_S_FAILURE\n")); Srb->SrbStatus = SRB_STATUS_ERROR; break; default: Srb->SrbStatus = SRB_STATUS_ERROR; RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("Unknown response %d\n", resp->response)); break; } if (Srb->SrbStatus != SRB_STATUS_SUCCESS) { PSENSE_DATA pSense = (PSENSE_DATA) Srb->SenseInfoBuffer; if (Srb->SenseInfoBufferLength >= FIELD_OFFSET(SENSE_DATA, CommandSpecificInformation)) { memcpy(Srb->SenseInfoBuffer, resp->sense, min(resp->sense_len, Srb->SenseInfoBufferLength)); if (Srb->SrbStatus == SRB_STATUS_ERROR) { Srb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID; } } Srb->DataTransferLength = 0; } else if (srbExt->Xfer && Srb->DataTransferLength > srbExt->Xfer) { Srb->DataTransferLength = srbExt->Xfer; Srb->SrbStatus = SRB_STATUS_DATA_OVERRUN; } if (srbExt && srbExt->Xfer && Srb->DataTransferLength > srbExt->Xfer) { Srb->DataTransferLength = srbExt->Xfer; Srb->SrbStatus = SRB_STATUS_DATA_OVERRUN; } --adaptExt->in_fly; StorPortNotification(RequestComplete, DeviceExtension, Srb); if (adaptExt->in_fly > 0) { adaptExt->vq[2]->vq_ops->kick(adaptExt->vq[2]); } } return TRUE; } return FALSE; }