BOOLEAN KickEvent( IN PVOID DeviceExtension, IN PVirtIOSCSIEventNode EventNode ) { PADAPTER_EXTENSION adaptExt; ULONG fragLen; ENTER_FN(); adaptExt = (PADAPTER_EXTENSION)DeviceExtension; RtlZeroMemory((PVOID)EventNode, sizeof(VirtIOSCSIEventNode)); EventNode->sg.physAddr = StorPortGetPhysicalAddress(DeviceExtension, NULL, &EventNode->event, &fragLen); EventNode->sg.length = sizeof(VirtIOSCSIEvent); return SynchronizedKickEventRoutine(DeviceExtension, (PVOID)EventNode); EXIT_FN(); }
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; }