VOID FORCEINLINE CompleteDPC( IN PVOID DeviceExtension, IN pblk_req vbr, IN ULONG MessageID ) { PSCSI_REQUEST_BLOCK Srb = (PSCSI_REQUEST_BLOCK)vbr->req; PADAPTER_EXTENSION adaptExt = (PADAPTER_EXTENSION)DeviceExtension; #ifndef USE_STORPORT PRHEL_SRB_EXTENSION srbExt = (PRHEL_SRB_EXTENSION)Srb->SrbExtension; UNREFERENCED_PARAMETER( MessageID ); #endif RemoveEntryList(&vbr->list_entry); #ifdef USE_STORPORT if(!adaptExt->dump_mode && adaptExt->dpc_ok) { InsertTailList(&adaptExt->complete_list, &vbr->list_entry); StorPortIssueDpc(DeviceExtension, &adaptExt->completion_dpc, ULongToPtr(MessageID), NULL); return; } CompleteSRB(DeviceExtension, Srb); #else if (Srb->DataTransferLength > srbExt->Xfer) { Srb->DataTransferLength = srbExt->Xfer; Srb->SrbStatus = SRB_STATUS_DATA_OVERRUN; } ScsiPortNotification(RequestComplete, DeviceExtension, Srb); if(srbExt->call_next) { ScsiPortNotification(NextLuRequest, DeviceExtension, Srb->PathId, Srb->TargetId, Srb->Lun); } if (adaptExt->flush_state == FlushRequested) { adaptExt->flush_state = FlushInflight; RhelDoFlush(DeviceExtension); } #endif }
BOOLEAN VirtIoMSInterruptRoutine ( IN PVOID DeviceExtension, IN ULONG MessageID ) { pblk_req vbr; unsigned int len; PADAPTER_EXTENSION adaptExt; PSCSI_REQUEST_BLOCK Srb; BOOLEAN isInterruptServiced = FALSE; PRHEL_SRB_EXTENSION srbExt; adaptExt = (PADAPTER_EXTENSION)DeviceExtension; RhelDbgPrint(TRACE_LEVEL_VERBOSE, ("<--->%s : MessageID 0x%x\n", __FUNCTION__, MessageID)); if (MessageID == 0) { RhelGetDiskGeometry(DeviceExtension); return 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) { --adaptExt->in_fly; CompleteSRB(DeviceExtension, Srb); } else if (vbr->out_hdr.type == VIRTIO_BLK_T_GET_ID) { adaptExt->sn_ok = TRUE; } else if (Srb) { --adaptExt->in_fly; srbExt = (PRHEL_SRB_EXTENSION)Srb->SrbExtension; if (srbExt->fua == TRUE) { 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, MessageID); } } isInterruptServiced = TRUE; } if (adaptExt->in_fly > 0) { adaptExt->vq->vq_ops->kick(adaptExt->vq); } return isInterruptServiced; }
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 VirtIoStartIo( IN PVOID DeviceExtension, IN PSCSI_REQUEST_BLOCK Srb ) { PCDB cdb = (PCDB)&Srb->Cdb[0]; PADAPTER_EXTENSION adaptExt; adaptExt = (PADAPTER_EXTENSION)DeviceExtension; switch (Srb->Function) { case SRB_FUNCTION_EXECUTE_SCSI: case SRB_FUNCTION_IO_CONTROL: { break; } case SRB_FUNCTION_PNP: case SRB_FUNCTION_POWER: case SRB_FUNCTION_RESET_DEVICE: case SRB_FUNCTION_RESET_LOGICAL_UNIT: { Srb->SrbStatus = SRB_STATUS_SUCCESS; CompleteSRB(DeviceExtension, Srb); return TRUE; } case SRB_FUNCTION_FLUSH: case SRB_FUNCTION_SHUTDOWN: { Srb->SrbStatus = SRB_STATUS_PENDING; Srb->ScsiStatus = SCSISTAT_GOOD; if (!RhelDoFlush(DeviceExtension, Srb, TRUE)) { Srb->SrbStatus = SRB_STATUS_ERROR; CompleteSRB(DeviceExtension, Srb); } return TRUE; } default: { Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST; CompleteSRB(DeviceExtension, Srb); return TRUE; } } switch (cdb->CDB6GENERIC.OperationCode) { case SCSIOP_MODE_SENSE: { Srb->SrbStatus = RhelScsiGetModeSense(DeviceExtension, Srb); CompleteSRB(DeviceExtension, Srb); return TRUE; } case SCSIOP_INQUIRY: { Srb->SrbStatus = RhelScsiGetInquiryData(DeviceExtension, Srb); CompleteSRB(DeviceExtension, Srb); return TRUE; } case SCSIOP_READ_CAPACITY16: case SCSIOP_READ_CAPACITY: { Srb->SrbStatus = RhelScsiGetCapacity(DeviceExtension, Srb); CompleteSRB(DeviceExtension, Srb); return TRUE; } case SCSIOP_WRITE: case SCSIOP_WRITE16: { if (CHECKBIT(adaptExt->features, VIRTIO_BLK_F_RO)) { PSENSE_DATA senseBuffer = (PSENSE_DATA) Srb->SenseInfoBuffer; Srb->SrbStatus = SRB_STATUS_ERROR; Srb->ScsiStatus = SCSISTAT_CHECK_CONDITION; senseBuffer->SenseKey = SCSI_SENSE_DATA_PROTECT; senseBuffer->AdditionalSenseCode = SCSI_ADWRITE_PROTECT; CompleteSRB(DeviceExtension, Srb); return TRUE; } } case SCSIOP_READ: case SCSIOP_READ16: { Srb->SrbStatus = SRB_STATUS_PENDING; if(!RhelDoReadWrite(DeviceExtension, Srb)) { Srb->SrbStatus = SRB_STATUS_BUSY; CompleteSRB(DeviceExtension, Srb); } return TRUE; } case SCSIOP_START_STOP_UNIT: { Srb->SrbStatus = SRB_STATUS_SUCCESS; CompleteSRB(DeviceExtension, Srb); return TRUE; } case SCSIOP_REQUEST_SENSE: case SCSIOP_TEST_UNIT_READY: case SCSIOP_RESERVE_UNIT: case SCSIOP_RESERVE_UNIT10: case SCSIOP_RELEASE_UNIT: case SCSIOP_RELEASE_UNIT10: case SCSIOP_VERIFY: case SCSIOP_VERIFY16: case SCSIOP_MEDIUM_REMOVAL: { Srb->SrbStatus = SRB_STATUS_SUCCESS; Srb->ScsiStatus = SCSISTAT_GOOD; CompleteSRB(DeviceExtension, Srb); return TRUE; } case SCSIOP_SYNCHRONIZE_CACHE: case SCSIOP_SYNCHRONIZE_CACHE16: { Srb->SrbStatus = SRB_STATUS_PENDING; Srb->ScsiStatus = SCSISTAT_GOOD; if (!RhelDoFlush(DeviceExtension, Srb, TRUE)) { Srb->SrbStatus = SRB_STATUS_ERROR; CompleteSRB(DeviceExtension, Srb); } return TRUE; } default: { break; } } if (cdb->CDB12.OperationCode == SCSIOP_REPORT_LUNS) { Srb->SrbStatus = RhelScsiReportLuns(DeviceExtension, Srb); CompleteSRB(DeviceExtension, Srb); return TRUE; } Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST; CompleteSRB(DeviceExtension, Srb); return TRUE; }
VOID CompleteDpcRoutine( IN PSTOR_DPC Dpc, IN PVOID Context, IN PVOID SystemArgument1, IN PVOID SystemArgument2 ) { STOR_LOCK_HANDLE LockHandle; PADAPTER_EXTENSION adaptExt = (PADAPTER_EXTENSION)Context; #ifdef MSI_SUPPORTED ULONG MessageID = PtrToUlong(SystemArgument1); ULONG OldIrql; #endif #ifdef MSI_SUPPORTED if(adaptExt->msix_vectors) { StorPortAcquireMSISpinLock (Context, MessageID, &OldIrql); } else { #endif StorPortAcquireSpinLock ( Context, InterruptLock , NULL, &LockHandle); #ifdef MSI_SUPPORTED } #endif while (!IsListEmpty(&adaptExt->complete_list)) { PSCSI_REQUEST_BLOCK Srb; PRHEL_SRB_EXTENSION srbExt; pblk_req vbr; vbr = (pblk_req) RemoveHeadList(&adaptExt->complete_list); Srb = (PSCSI_REQUEST_BLOCK)vbr->req; srbExt = (PRHEL_SRB_EXTENSION)Srb->SrbExtension; #ifdef MSI_SUPPORTED if(adaptExt->msix_vectors) { StorPortReleaseMSISpinLock (Context, MessageID, OldIrql); } else { #endif StorPortReleaseSpinLock (Context, &LockHandle); #ifdef MSI_SUPPORTED } #endif if (Srb->DataTransferLength > srbExt->Xfer) { Srb->DataTransferLength = srbExt->Xfer; Srb->SrbStatus = SRB_STATUS_DATA_OVERRUN; } ScsiPortNotification(RequestComplete, Context, Srb); #ifdef MSI_SUPPORTED if(adaptExt->msix_vectors) { StorPortAcquireMSISpinLock (Context, MessageID, &OldIrql); } else { #endif StorPortAcquireSpinLock ( Context, InterruptLock , NULL, &LockHandle); #ifdef MSI_SUPPORTED } #endif } #ifdef MSI_SUPPORTED if(adaptExt->msix_vectors) { StorPortReleaseMSISpinLock (Context, MessageID, OldIrql); } else { #endif StorPortReleaseSpinLock (Context, &LockHandle); #ifdef MSI_SUPPORTED } #endif if (adaptExt->flush_state == FlushRequested) { adaptExt->flush_state = FlushInflight; RhelDoFlush(Context); } return; }