BOOLEAN VirtRngEvtInterruptIsr(IN WDFINTERRUPT Interrupt, IN ULONG MessageId) { PDEVICE_CONTEXT context = GetDeviceContext( WdfInterruptGetDevice(Interrupt)); WDF_INTERRUPT_INFO info; BOOLEAN serviced; TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INTERRUPT, "--> %!FUNC! Interrupt: %p MessageId: %u", Interrupt, MessageId); WDF_INTERRUPT_INFO_INIT(&info); WdfInterruptGetInfo(context->WdfInterrupt, &info); if ((info.MessageSignaled && (MessageId == 0)) || VirtIODeviceISR(&context->VirtDevice)) { WdfInterruptQueueDpcForIsr(Interrupt); serviced = TRUE; } else { serviced = FALSE; } TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INTERRUPT, "<-- %!FUNC!"); return serviced; }
BOOLEAN VirtIoInterrupt( IN PVOID DeviceExtension ) { pblk_req vbr; unsigned int len; PADAPTER_EXTENSION adaptExt; BOOLEAN isInterruptServiced = FALSE; PSCSI_REQUEST_BLOCK Srb; ULONG intReason = 0; adaptExt = (PADAPTER_EXTENSION)DeviceExtension; RhelDbgPrint(TRACE_LEVEL_VERBOSE, ("%s (%d)\n", __FUNCTION__, KeGetCurrentIrql())); intReason = VirtIODeviceISR((VirtIODevice*)DeviceExtension); if ( intReason == 1) { isInterruptServiced = TRUE; while((vbr = (pblk_req)adaptExt->vq->vq_ops->get_buf(adaptExt->vq, &len)) != NULL) { Srb = (PSCSI_REQUEST_BLOCK)vbr->req; if (Srb) { switch (vbr->status) { case VIRTIO_BLK_S_OK: Srb->SrbStatus = SRB_STATUS_SUCCESS; break; case VIRTIO_BLK_S_UNSUPP: Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST; break; default: Srb->SrbStatus = SRB_STATUS_ERROR; RhelDbgPrint(TRACE_LEVEL_ERROR, ("SRB_STATUS_ERROR\n")); break; } } if (vbr->out_hdr.type == VIRTIO_BLK_T_FLUSH) { #ifdef USE_STORPORT --adaptExt->in_fly; #endif CompleteSRB(DeviceExtension, Srb); } else if (vbr->out_hdr.type == VIRTIO_BLK_T_GET_ID) { adaptExt->sn_ok = TRUE; } else if (Srb) { #ifdef USE_STORPORT --adaptExt->in_fly; #endif CompleteDPC(DeviceExtension, vbr, 0); } } } else if (intReason == 3) { adaptExt->rescan_geometry = TRUE; ScsiPortNotification( BusChangeDetected, DeviceExtension, 0); isInterruptServiced = TRUE; } #ifdef USE_STORPORT if (adaptExt->in_fly > 0) { adaptExt->vq->vq_ops->kick(adaptExt->vq); } #endif RhelDbgPrint(TRACE_LEVEL_VERBOSE, ("%s isInterruptServiced = %d\n", __FUNCTION__, isInterruptServiced)); return isInterruptServiced; }
/********************************************************** NDIS-required procedure for hardware interrupt handling Parameters: IN PVOID MiniportInterruptContext (actually Adapter context) OUT PBOOLEAN QueueDefaultInterruptDpc - set to TRUE for default DPC spawning OUT PULONG TargetProcessors Return value: TRUE if recognized ***********************************************************/ static BOOLEAN MiniportInterrupt( IN PVOID MiniportInterruptContext, OUT PBOOLEAN QueueDefaultInterruptDpc, OUT PULONG TargetProcessors ) { PARANDIS_ADAPTER *pContext = (PARANDIS_ADAPTER *)MiniportInterruptContext; ULONG status = VirtIODeviceISR(pContext->IODevice); *TargetProcessors = 0; if((status == 0) || (status == VIRTIO_NET_INVALID_INTERRUPT_STATUS)) { *QueueDefaultInterruptDpc = FALSE; return FALSE; } PARADNIS_STORE_LAST_INTERRUPT_TIMESTAMP(pContext); if(!pContext->bDeviceInitialized) { *QueueDefaultInterruptDpc = FALSE; return TRUE; } for (UINT i = 0; i < pContext->nPathBundles; i++) { pContext->pPathBundles[i].txPath.DisableInterrupts(); pContext->pPathBundles[i].rxPath.DisableInterrupts(); } if (pContext->bCXPathCreated) { pContext->CXPath.DisableInterrupts(); } *QueueDefaultInterruptDpc = TRUE; pContext->ulIrqReceived += 1; return true; }
BOOLEAN BalloonInterruptIsr( IN WDFINTERRUPT WdfInterrupt, IN ULONG MessageID ) { PDEVICE_CONTEXT devCtx = NULL; WDFDEVICE Device; UNREFERENCED_PARAMETER( MessageID ); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INTERRUPT, "--> %s\n", __FUNCTION__); Device = WdfInterruptGetDevice(WdfInterrupt); devCtx = GetDeviceContext(Device); if(VirtIODeviceISR(&devCtx->VDevice) > 0) { WdfInterruptQueueDpcForIsr( WdfInterrupt ); return TRUE; } return FALSE; }
BOOLEAN VirtIoInterrupt( IN PVOID DeviceExtension ) { pblk_req vbr; unsigned int len; PADAPTER_EXTENSION adaptExt; BOOLEAN isInterruptServiced = FALSE; PSCSI_REQUEST_BLOCK Srb; ULONG intReason = 0; PRHEL_SRB_EXTENSION srbExt; adaptExt = (PADAPTER_EXTENSION)DeviceExtension; RhelDbgPrint(TRACE_LEVEL_VERBOSE, ("%s (%d)\n", __FUNCTION__, KeGetCurrentIrql())); intReason = VirtIODeviceISR((VirtIODevice*)DeviceExtension); if ( intReason == 1) { isInterruptServiced = TRUE; while((vbr = (pblk_req)adaptExt->vq->vq_ops->get_buf(adaptExt->vq, &len)) != NULL) { Srb = (PSCSI_REQUEST_BLOCK)vbr->req; if (Srb) { switch (vbr->status) { case VIRTIO_BLK_S_OK: Srb->SrbStatus = SRB_STATUS_SUCCESS; break; case VIRTIO_BLK_S_UNSUPP: Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST; break; default: Srb->SrbStatus = SRB_STATUS_ERROR; RhelDbgPrint(TRACE_LEVEL_ERROR, ("SRB_STATUS_ERROR\n")); break; } } if (vbr->out_hdr.type == VIRTIO_BLK_T_FLUSH) { #ifdef USE_STORPORT --adaptExt->in_fly; #endif CompleteSRB(DeviceExtension, Srb); } else if (vbr->out_hdr.type == VIRTIO_BLK_T_GET_ID) { adaptExt->sn_ok = TRUE; } else if (Srb) { #ifdef USE_STORPORT --adaptExt->in_fly; #endif srbExt = (PRHEL_SRB_EXTENSION)Srb->SrbExtension; if (srbExt->fua) { RemoveEntryList(&vbr->list_entry); Srb->SrbStatus = SRB_STATUS_PENDING; Srb->ScsiStatus = SCSISTAT_GOOD; if (!RhelDoFlush(DeviceExtension, Srb, FALSE)) { Srb->SrbStatus = SRB_STATUS_ERROR; CompleteSRB(DeviceExtension, Srb); } else { srbExt->fua = FALSE; } } else { CompleteDPC(DeviceExtension, vbr, 0); } } } } else if (intReason == 3) { RhelGetDiskGeometry(DeviceExtension); isInterruptServiced = TRUE; } #ifdef USE_STORPORT if (adaptExt->in_fly > 0) { adaptExt->vq->vq_ops->kick(adaptExt->vq); } #endif RhelDbgPrint(TRACE_LEVEL_VERBOSE, ("%s isInterruptServiced = %d\n", __FUNCTION__, isInterruptServiced)); return isInterruptServiced; }
BOOLEAN VioScsiInterrupt( IN PVOID DeviceExtension ) { 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 (%d)\n", __FUNCTION__, KeGetCurrentIrql())); intReason = VirtIODeviceISR(&adaptExt->vdev); if ( intReason == 1) { isInterruptServiced = TRUE; 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 && 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]); } 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; } 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); } } RhelDbgPrint(TRACE_LEVEL_VERBOSE, ("%s isInterruptServiced = %d\n", __FUNCTION__, isInterruptServiced)); return isInterruptServiced; }