VOID
VioStorVQUnlock(
    IN PVOID DeviceExtension,
    IN ULONG MessageID,
    IN PSTOR_LOCK_HANDLE LockHandle,
    IN BOOLEAN isr
    )
{
    PADAPTER_EXTENSION  adaptExt;
    RhelDbgPrint(TRACE_LEVEL_VERBOSE, ("--->%s MessageID = %d\n", __FUNCTION__, MessageID));
    adaptExt = (PADAPTER_EXTENSION)DeviceExtension;

    if (!adaptExt->msix_enabled) {
        if (!isr) {
            StorPortReleaseSpinLock(DeviceExtension, LockHandle);
        }
    }
    else {
        if ((adaptExt->num_queues == 1) ||
            (!CHECKFLAG(adaptExt->perfFlags, STOR_PERF_CONCURRENT_CHANNELS))) {
            if (!isr) {
                StorPortReleaseMSISpinLock(DeviceExtension, (adaptExt->msix_one_vector ? 0 : MessageID), LockHandle->Context.OldIrql);
            }
        }
        else {
            NT_ASSERT(MessageID > 0);
            NT_ASSERT(MessageID <= adaptExt->num_queues);
            StorPortReleaseSpinLock(DeviceExtension, LockHandle);
        }
    }
    RhelDbgPrint(TRACE_LEVEL_VERBOSE, ("<---%s MessageID = %d\n", __FUNCTION__, MessageID));
}
Beispiel #2
0
VOID
PortBusChangeProcess (
    _In_ PAHCI_CHANNEL_EXTENSION ChannelExtension
    )
{
    AHCI_SERIAL_ATA_CONTROL sctl;
    STOR_LOCK_HANDLE        lockhandle = {0};

  //1 if link speed was limited, restore the supported value.
    sctl.AsUlong = StorPortReadRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->SCTL.AsUlong);
    if ( (sctl.SPD != 0) &&
         (sctl.SPD != ChannelExtension->AdapterExtension->CAP.ISS) ) {

        sctl.SPD = 0;   //AHCI 3.3.11 --- 0h  No speed negotiation restrictions
        StorPortWriteRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->SCTL.AsUlong, sctl.AsUlong);
    }

  //2 Kicks off the Start Channel state machine
    StorPortAcquireSpinLock(ChannelExtension->AdapterExtension, InterruptLock, NULL, &lockhandle);
    AhciPortReset(ChannelExtension, TRUE);    // all requests should be completed
    StorPortReleaseSpinLock(ChannelExtension->AdapterExtension, &lockhandle);

  //3 Requests rescan on this port, ignore the return status of this API. Using STATE_CHANGE_TARGET to make sure a REPORT LUNS command coming from Storport.
    StorPortStateChangeDetected(ChannelExtension->AdapterExtension,
                                STATE_CHANGE_TARGET,
                                (PSTOR_ADDRESS)&ChannelExtension->DeviceExtension[0].DeviceAddress,
                                0,
                                AhciBusChangeCallback,
                                NULL);

    PortReleaseActiveReference(ChannelExtension, NULL);
}
ULONG
VioScsiReleaseSpinLock(
    IN PVOID DeviceExtension,
    IN ULONG MessageID,
    IN PSTOR_LOCK_HANDLE LockHandle
    )
{
    PADAPTER_EXTENSION  adaptExt;
    ULONG               status = STOR_STATUS_SUCCESS;

ENTER_FN();
    adaptExt = (PADAPTER_EXTENSION)DeviceExtension;
    if (adaptExt->num_queues > 1) {
        status = StorPortReleaseMSISpinLock(DeviceExtension, MessageID, LockHandle->Context.OldIrql);
        if (status != STOR_STATUS_SUCCESS) {
            RhelDbgPrint(TRACE_LEVEL_ERROR, ("%s StorPortAcquireMSISpinLock returned status 0x%x\n", __FUNCTION__, status));
        }
    }
    else {
        StorPortReleaseSpinLock(DeviceExtension, LockHandle);
    }
    return status;
EXIT_FN();
}
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
    return;
}
Beispiel #5
0
VOID
AhciCompleteRequest(
    _In_ PAHCI_CHANNEL_EXTENSION ChannelExtension,
    _In_ PSTORAGE_REQUEST_BLOCK  Srb,
    _In_ BOOLEAN AtDIRQL
    )
/*++
    Wrapper for ComleteRequest to protect against completing the local SRB back to port driver who doesn't know anything about local SRB
It assumes:
    SRB is completely ready to be completed back to the SRB generator
It performs:
    1. If Srb has completion routine, put it in completion queue.
    2. Complete the command back to the owner. Do not complete the Local Srb.
Called by:
    AhciHwStartIo
    RequiresControllerResources
    ReleaseSlottedCommand

NOTE:
    The caller of this routine should call AhciGetNextIos or ActiveQueue to program the command (from Srb completion routine) to adapter

--*/
{
    PAHCI_SRB_EXTENSION srbExtension = GetSrbExtension(Srb);

  //1. If Srb acquired active reference or has completion routine, put it in completion queue. Otherwise, complete it.
    if ( ((srbExtension->Flags & ATA_FLAGS_ACTIVE_REFERENCE) != 0) ||
         (srbExtension->CompletionRoutine != NULL) ) {

        STOR_LOCK_HANDLE    lockhandle = {0};

        if (AtDIRQL == FALSE) {
            StorPortAcquireSpinLock(ChannelExtension->AdapterExtension, InterruptLock, NULL, &lockhandle);
            AddQueue(ChannelExtension, &ChannelExtension->CompletionQueue, Srb, 0xDEADBEEF, 0x90);
            StorPortReleaseSpinLock(ChannelExtension->AdapterExtension, &lockhandle);
        } else {
            AddQueue(ChannelExtension, &ChannelExtension->CompletionQueue, Srb, 0xDEADBEEF, 0x90);
        }

        if (!IsDumpMode(ChannelExtension->AdapterExtension)) {
            StorPortIssueDpc(ChannelExtension->AdapterExtension, &ChannelExtension->CompletionDpc, ChannelExtension, Srb);
        } else {
            AhciPortSrbCompletionDpcRoutine(&ChannelExtension->CompletionDpc, ChannelExtension->AdapterExtension, ChannelExtension, Srb);
        }

    } else {
      //2. Complete the command back to the owner
        if (IsMiniportInternalSrb(ChannelExtension, Srb)) {
            RecordExecutionHistory(ChannelExtension, 0x20000045); //Exit AhciCompleteRequest,  Local SRB
            return;
        } else {
            NT_ASSERT(Srb->SrbStatus != SRB_STATUS_PENDING);
            StorPortNotification(RequestComplete, ChannelExtension->AdapterExtension, Srb);
        }
    }

    if (LogExecuteFullDetail(ChannelExtension->AdapterExtension->LogFlags)) {
        RecordExecutionHistory(ChannelExtension, 0x10000045); //Exit AhciCompleteRequest, SRB from port driver
    }

    return;
}
BOOLEAN
SendSRB(
    IN PVOID DeviceExtension,
    IN PSCSI_REQUEST_BLOCK Srb
    )
{
    PADAPTER_EXTENSION  adaptExt = (PADAPTER_EXTENSION)DeviceExtension;
    PSRB_EXTENSION      srbExt   = (PSRB_EXTENSION)Srb->SrbExtension;
    PVOID               va = NULL;
    ULONGLONG           pa = 0;
    ULONG               QueueNumber = 0;
    ULONG               OldIrql = 0;
    ULONG               MessageId = 0;
    BOOLEAN             kick = FALSE;
    STOR_LOCK_HANDLE    LockHandle = { 0 };
    ULONG               status = STOR_STATUS_SUCCESS;
ENTER_FN();
    SET_VA_PA();
    RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("Srb %p issued on %d::%d QueueNumber %d\n",
                 Srb, srbExt->procNum.Group, srbExt->procNum.Number, QueueNumber));

    if (adaptExt->num_queues > 1) {
        QueueNumber = adaptExt->cpu_to_vq_map[srbExt->procNum.Number];
        MessageId = QueueNumber + 1;
        if (CHECKFLAG(adaptExt->perfFlags, STOR_PERF_OPTIMIZE_FOR_COMPLETION_DURING_STARTIO)) {
            ProcessQueue(DeviceExtension, MessageId, FALSE);
        }
//        status = StorPortAcquireMSISpinLock(DeviceExtension, MessageId, &OldIrql);
        if (status != STOR_STATUS_SUCCESS) {
            RhelDbgPrint(TRACE_LEVEL_ERROR, ("%s StorPortAcquireMSISpinLock returned status 0x%x\n", __FUNCTION__, status));
        }
    }
    else {
        QueueNumber = VIRTIO_SCSI_REQUEST_QUEUE_0;
        StorPortAcquireSpinLock(DeviceExtension, InterruptLock, NULL, &LockHandle);
    }
    if (virtqueue_add_buf(adaptExt->vq[QueueNumber],
                     &srbExt->sg[0],
                     srbExt->out, srbExt->in,
                     &srbExt->cmd, va, pa) >= 0){
        kick = TRUE;
    }
    else {
        RhelDbgPrint(TRACE_LEVEL_WARNING, ("%s Cant add packet to queue.\n", __FUNCTION__));
//FIXME
    }
    if (adaptExt->num_queues > 1) {
//        status = StorPortReleaseMSISpinLock(DeviceExtension, MessageId, OldIrql);
        if (status != STOR_STATUS_SUCCESS) {
            RhelDbgPrint(TRACE_LEVEL_ERROR, ("%s StorPortReleaseMSISpinLock returned status 0x%x\n", __FUNCTION__, status));
        }
    }
    else {
        StorPortReleaseSpinLock(DeviceExtension, &LockHandle);
    }
    if (kick == TRUE) {
        virtqueue_kick(adaptExt->vq[QueueNumber]);
    }
    return kick;
EXIT_FN();
}