ASSERT3U(Srb->SrbStatus, !=, SRB_STATUS_PENDING);
- ++Adapter->Completed;
+ InterlockedIncrement((PLONG)&Adapter->Completed);
StorPortNotification(RequestComplete, Adapter, Srb);
}
return TRUE;
}
-
static FORCEINLINE VOID
__AdapterSrbPnp(
IN PXENVBD_ADAPTER Adapter,
{
PXENVBD_ADAPTER Adapter = DevExt;
PXENVBD_SRBEXT SrbExt = Srb->SrbExtension;
+ PXENVBD_TARGET Target;
InitSrbExt(Srb);
+ InterlockedIncrement((PLONG)&Adapter->BuildIo);
switch (Srb->Function) {
case SRB_FUNCTION_EXECUTE_SCSI:
AdapterPullupSrb(Adapter, Srb);
- // Intentional fall through
+ Target = AdapterGetTarget(Adapter, Srb->TargetId);
+ if (Target == NULL)
+ Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
+ else
+ TargetPrepareIo(Target, SrbExt);
+ break;
+
case SRB_FUNCTION_RESET_DEVICE:
case SRB_FUNCTION_FLUSH:
case SRB_FUNCTION_SHUTDOWN:
- ++Adapter->BuildIo;
- return TRUE;
+ Target = AdapterGetTarget(Adapter, Srb->TargetId);
+ if (Target == NULL)
+ Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
+ else
+ Srb->SrbStatus = SRB_STATUS_PENDING;
+ break;
- // dont pass to StartIo
case SRB_FUNCTION_PNP:
__AdapterSrbPnp(Adapter, (PSCSI_PNP_REQUEST_BLOCK)Srb);
Srb->SrbStatus = SRB_STATUS_SUCCESS;
break;
+
case SRB_FUNCTION_ABORT_COMMAND:
Srb->SrbStatus = SRB_STATUS_ABORT_FAILED;
break;
+
case SRB_FUNCTION_RESET_BUS:
AdapterHwResetBus(Adapter, Srb->PathId);
Srb->SrbStatus = SRB_STATUS_SUCCESS;
break;
}
+ if (Srb->SrbStatus == SRB_STATUS_PENDING)
+ return TRUE;
+
AdapterCompleteSrb(Adapter, SrbExt);
return FALSE;
}
{
PXENVBD_ADAPTER Adapter = DevExt;
PXENVBD_SRBEXT SrbExt = Srb->SrbExtension;
+ BOOLEAN WasQueued = FALSE;
PXENVBD_TARGET Target;
Target = AdapterGetTarget(Adapter, Srb->TargetId);
- if (Target == NULL)
- goto fail1;
+ if (Target == NULL) {
+ Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
+ goto done;
+ }
- ++Adapter->StartIo;
- if (TargetStartIo(Target, SrbExt))
- AdapterCompleteSrb(Adapter, SrbExt);
+ switch (Srb->Function) {
+ case SRB_FUNCTION_EXECUTE_SCSI:
+ WasQueued = TargetStartIo(Target, SrbExt);
+ break;
- return TRUE;
+ case SRB_FUNCTION_RESET_DEVICE:
+ TargetReset(Target);
+ Srb->SrbStatus = SRB_STATUS_SUCCESS;
+ break;
-fail1:
- Srb->SrbStatus = SRB_STATUS_INVALID_TARGET_ID;
- AdapterCompleteSrb(Adapter, SrbExt);
+ case SRB_FUNCTION_FLUSH:
+ TargetFlush(Target, SrbExt);
+ WasQueued = TRUE;
+ break;
+
+ case SRB_FUNCTION_SHUTDOWN:
+ TargetShutdown(Target, SrbExt);
+ WasQueued = TRUE;
+ break;
+
+ default:
+ ASSERT(FALSE);
+ break;
+ }
+
+done:
+ // if SRB WasQueued, the SRB will be completed when the Queues are processed
+ // Note: there could be a race in updating the Srb->SrbStatus field if the
+ // processing of the queue completes before returning from TargetStartIo
+ if (!WasQueued)
+ AdapterCompleteSrb(Adapter, SrbExt);
return TRUE;
}
Srb->SrbStatus = SRB_STATUS_SUCCESS;
}
-//=============================================================================
-// StorPort Methods
-__checkReturn
static FORCEINLINE BOOLEAN
-__TargetExecuteScsi(
- __in PXENVBD_TARGET Target,
- __in PSCSI_REQUEST_BLOCK Srb
+__ValidateSrbForTarget(
+ IN PXENVBD_TARGET Target,
+ IN PSCSI_REQUEST_BLOCK Srb
)
{
- const UCHAR Operation = Cdb_OperationEx(Srb);
- PXENVBD_DISKINFO DiskInfo = FrontendGetDiskInfo(Target->Frontend);
+ const UCHAR Operation = Cdb_OperationEx(Srb);
- if (DiskInfo->DiskInfo & VDISK_READONLY) {
- Trace("Target[%d] : (%08x) Read-Only, fail SRB (%02x:%s)\n", TargetGetTargetId(Target),
- DiskInfo->DiskInfo, Operation, Cdb_OperationName(Operation));
- Srb->ScsiStatus = 0x40; // SCSI_ABORT
- return TRUE;
+ if (Target == NULL) {
+ Error("Invalid Target(NULL) (%02x:%s)\n",
+ Operation,
+ Cdb_OperationName(Operation));
+ Srb->SrbStatus = SRB_STATUS_INVALID_TARGET_ID;
+ return FALSE;
+ }
+
+ if (Srb->PathId != 0) {
+ Error("Target[%d] : Invalid PathId(%d) (%02x:%s)\n",
+ TargetGetTargetId(Target),
+ Srb->PathId,
+ Operation,
+ Cdb_OperationName(Operation));
+ Srb->SrbStatus = SRB_STATUS_INVALID_PATH_ID;
+ return FALSE;
}
- // idea: check pdo state here. still push to freshsrbs
+ if (Srb->Lun != 0) {
+ Error("Target[%d] : Invalid Lun(%d) (%02x:%s)\n",
+ TargetGetTargetId(Target),
+ Srb->Lun,
+ Operation,
+ Cdb_OperationName(Operation));
+ Srb->SrbStatus = SRB_STATUS_INVALID_LUN;
+ return FALSE;
+ }
+
+ if (TargetIsMissing(Target)) {
+ Error("Target[%d] : %s (%s) (%02x:%s)\n",
+ TargetGetTargetId(Target),
+ Target->Missing ? "MISSING" : "NOT_MISSING",
+ Target->Reason,
+ Operation,
+ Cdb_OperationName(Operation));
+ Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+VOID
+TargetPrepareIo(
+ IN PXENVBD_TARGET Target,
+ IN PXENVBD_SRBEXT SrbExt
+ )
+{
+ PSCSI_REQUEST_BLOCK Srb = SrbExt->Srb;
+
+ if (!__ValidateSrbForTarget(Target, Srb))
+ return;
+
+ Srb->SrbStatus = SRB_STATUS_PENDING;
+}
+
+BOOLEAN
+TargetStartIo(
+ IN PXENVBD_TARGET Target,
+ IN PXENVBD_SRBEXT SrbExt
+ )
+{
+ PSCSI_REQUEST_BLOCK Srb = SrbExt->Srb;
+ const UCHAR Operation = Cdb_OperationEx(Srb);
+ BOOLEAN WasQueued = FALSE;
+
+ ASSERT(__ValidateSrbForTarget(Target, Srb));
+
switch (Operation) {
case SCSIOP_READ:
case SCSIOP_WRITE:
- return TargetReadWrite(Target, Srb);
+ if (!TargetReadWrite(Target, Srb))
+ WasQueued = TRUE;
break;
- case SCSIOP_SYNCHRONIZE_CACHE:
- return TargetSyncCache(Target, Srb);
+ case SCSIOP_UNMAP:
+ if (!TargetUnmap(Target, Srb))
+ WasQueued = TRUE;
break;
- case SCSIOP_UNMAP:
- return TargetUnmap(Target, Srb);
+ case SCSIOP_SYNCHRONIZE_CACHE:
+ if (!TargetSyncCache(Target, Srb))
+ WasQueued = TRUE;
break;
case SCSIOP_INQUIRY:
AdapterSetDeviceQueueDepth(TargetGetAdapter(Target),
TargetGetTargetId(Target));
- PdoInquiry(TargetGetTargetId(Target), FrontendGetInquiry(Target->Frontend), Srb);
+ PdoInquiry(TargetGetTargetId(Target),
+ FrontendGetInquiry(Target->Frontend),
+ Srb);
break;
+
case SCSIOP_MODE_SENSE:
TargetModeSense(Target, Srb);
break;
+
case SCSIOP_REQUEST_SENSE:
TargetRequestSense(Target, Srb);
break;
+
case SCSIOP_REPORT_LUNS:
TargetReportLuns(Target, Srb);
break;
+
case SCSIOP_READ_CAPACITY:
TargetReadCapacity(Target, Srb);
break;
+
case SCSIOP_READ_CAPACITY16:
TargetReadCapacity16(Target, Srb);
break;
+
case SCSIOP_MEDIUM_REMOVAL:
case SCSIOP_TEST_UNIT_READY:
case SCSIOP_RESERVE_UNIT:
case SCSIOP_RELEASE_UNIT10:
case SCSIOP_VERIFY:
case SCSIOP_VERIFY16:
- Srb->SrbStatus = SRB_STATUS_SUCCESS;
- break;
case SCSIOP_START_STOP_UNIT:
- Trace("Target[%d] : Start/Stop Unit (%02X)\n", TargetGetTargetId(Target), Srb->Cdb[4]);
Srb->SrbStatus = SRB_STATUS_SUCCESS;
break;
+
default:
- Trace("Target[%d] : Unsupported CDB (%02x:%s)\n", TargetGetTargetId(Target), Operation, Cdb_OperationName(Operation));
+ Trace("Target[%d] : Unsupported CDB (%02x:%s)\n",
+ TargetGetTargetId(Target),
+ Operation,
+ Cdb_OperationName(Operation));
+ Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
break;
}
- return TRUE;
-}
-
-static FORCEINLINE BOOLEAN
-__TargetQueueShutdown(
- __in PXENVBD_TARGET Target,
- __in PSCSI_REQUEST_BLOCK Srb
- )
-{
- PXENVBD_SRBEXT SrbExt = GetSrbExt(Srb);
- PXENVBD_NOTIFIER Notifier = FrontendGetNotifier(Target->Frontend);
-
- QueueAppend(&Target->ShutdownSrbs, &SrbExt->Entry);
- NotifierKick(Notifier);
-
- return FALSE;
-}
-
-static FORCEINLINE BOOLEAN
-__TargetReset(
- __in PXENVBD_TARGET Target,
- __in PSCSI_REQUEST_BLOCK Srb
- )
-{
- Verbose("Target[%u] ====>\n", TargetGetTargetId(Target));
-
- TargetReset(Target);
- Srb->SrbStatus = SRB_STATUS_SUCCESS;
-
- Verbose("Target[%u] <====\n", TargetGetTargetId(Target));
- return TRUE;
+ return WasQueued;
}
-__checkReturn
-static FORCEINLINE BOOLEAN
-__ValidateSrbForTarget(
- __in PXENVBD_TARGET Target,
- __in PSCSI_REQUEST_BLOCK Srb
+VOID
+TargetReset(
+ IN PXENVBD_TARGET Target
)
{
- const UCHAR Operation = Cdb_OperationEx(Srb);
-
- if (Target == NULL) {
- Error("Invalid Target(NULL) (%02x:%s)\n",
- Operation, Cdb_OperationName(Operation));
- Srb->SrbStatus = SRB_STATUS_INVALID_TARGET_ID;
- return FALSE;
- }
+ Verbose("[%u] =====>\n", TargetGetTargetId(Target));
- if (Srb->PathId != 0) {
- Error("Target[%d] : Invalid PathId(%d) (%02x:%s)\n",
- TargetGetTargetId(Target), Srb->PathId, Operation, Cdb_OperationName(Operation));
- Srb->SrbStatus = SRB_STATUS_INVALID_PATH_ID;
- return FALSE;
- }
+ __TargetPauseDataPath(Target, TRUE);
- if (Srb->Lun != 0) {
- Error("Target[%d] : Invalid Lun(%d) (%02x:%s)\n",
- TargetGetTargetId(Target), Srb->Lun, Operation, Cdb_OperationName(Operation));
- Srb->SrbStatus = SRB_STATUS_INVALID_LUN;
- return FALSE;
+ if (QueueCount(&Target->SubmittedReqs)) {
+ Error("Target[%d] : backend has %u outstanding requests after a TargetReset\n",
+ TargetGetTargetId(Target),
+ QueueCount(&Target->SubmittedReqs));
}
- if (TargetIsMissing(Target)) {
- Error("Target[%d] : %s (%s) (%02x:%s)\n",
- TargetGetTargetId(Target), Target->Missing ? "MISSING" : "NOT_MISSING", Target->Reason, Operation, Cdb_OperationName(Operation));
- Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
- return FALSE;
- }
+ __TargetUnpauseDataPath(Target);
- return TRUE;
+ Verbose("[%u] <=====\n", TargetGetTargetId(Target));
}
-BOOLEAN
-TargetStartIo(
+VOID
+TargetFlush(
IN PXENVBD_TARGET Target,
IN PXENVBD_SRBEXT SrbExt
)
{
- PSCSI_REQUEST_BLOCK Srb = SrbExt->Srb;
-
- if (!__ValidateSrbForTarget(Target, Srb))
- return TRUE;
-
- switch (Srb->Function) {
- case SRB_FUNCTION_EXECUTE_SCSI:
- return __TargetExecuteScsi(Target, Srb);
-
- case SRB_FUNCTION_RESET_DEVICE:
- return __TargetReset(Target, Srb);
-
- case SRB_FUNCTION_FLUSH:
- case SRB_FUNCTION_SHUTDOWN:
- return __TargetQueueShutdown(Target, Srb);
-
- default:
- return TRUE;
- }
+ QueueAppend(&Target->ShutdownSrbs, &SrbExt->Entry);
+ NotifierKick(FrontendGetNotifier(Target->Frontend));
}
VOID
-TargetReset(
- __in PXENVBD_TARGET Target
+TargetShutdown(
+ IN PXENVBD_TARGET Target,
+ IN PXENVBD_SRBEXT SrbExt
)
{
- Trace("Target[%d] ====> (Irql=%d)\n", TargetGetTargetId(Target), KeGetCurrentIrql());
-
- __TargetPauseDataPath(Target, TRUE);
-
- if (QueueCount(&Target->SubmittedReqs)) {
- Error("Target[%d] : backend has %u outstanding requests after a TargetReset\n",
- TargetGetTargetId(Target), QueueCount(&Target->SubmittedReqs));
- }
-
- __TargetUnpauseDataPath(Target);
-
- Trace("Target[%d] <==== (Irql=%d)\n", TargetGetTargetId(Target), KeGetCurrentIrql());
+ QueueAppend(&Target->ShutdownSrbs, &SrbExt->Entry);
+ NotifierKick(FrontendGetNotifier(Target->Frontend));
}
-
VOID
TargetSrbPnp(
__in PXENVBD_TARGET Target,