VOID VioStorVQLock( IN PVOID DeviceExtension, IN ULONG MessageID, IN OUT 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) { StorPortAcquireSpinLock(DeviceExtension, InterruptLock, NULL, LockHandle); } } else { if ((adaptExt->num_queues == 1) || (!CHECKFLAG(adaptExt->perfFlags, STOR_PERF_CONCURRENT_CHANNELS))) { if (!isr) { ULONG oldIrql = 0; StorPortAcquireMSISpinLock(DeviceExtension, (adaptExt->msix_one_vector ? 0 : MessageID), &oldIrql); LockHandle->Context.OldIrql = (KIRQL)oldIrql; } } else { NT_ASSERT(MessageID > 0); NT_ASSERT(MessageID <= adaptExt->num_queues); StorPortAcquireSpinLock(DeviceExtension, StartIoLock, &adaptExt->dpc[MessageID - 1], LockHandle); } } RhelDbgPrint(TRACE_LEVEL_VERBOSE, ("<---%s MessageID = %d\n", __FUNCTION__, MessageID)); }
ULONG VioScsiAcquireSpinLock( 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) { ULONG oldIrql = 0; status = StorPortAcquireMSISpinLock(DeviceExtension, MessageID, &oldIrql); LockHandle->Context.OldIrql = (KIRQL)oldIrql; if (status != STOR_STATUS_SUCCESS) { RhelDbgPrint(TRACE_LEVEL_ERROR, ("%s StorPortAcquireMSISpinLock returned status 0x%x\n", __FUNCTION__, status)); } } else { StorPortAcquireSpinLock(DeviceExtension, InterruptLock, NULL, LockHandle); } return status; EXIT_FN(); }
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); }
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; }
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(); }