📄 mvialcommon.c
字号:
/*******************************************************************************
* (c), Copyright 2001, Marvell International Ltd. *
* THIS CODE CONTAINS CONFIDENTIAL INFORMATION OF MARVELL SEMICONDUCTOR, INC. *
* NO RIGHTS ARE GRANTED HEREIN UNDER ANY PATENT, MASK WORK RIGHT OR COPYRIGHT *
* OF MARVELL OR ANY THIRD PARTY. MARVELL RESERVES THE RIGHT AT ITS SOLE *
* DISCRETION TO REQUEST THAT THIS CODE BE IMMEDIATELY RETURNED TO MARVELL. *
* THIS CODE IS PROVIDED "AS IS". MARVELL MAKES NO WARRANTIES, EXPRESSED, *
* IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, COMPLETENESS OR PERFORMANCE. *
********************************************************************************
* mvIALCommon.c
*
* DESCRIPTION:
* C implementation for IAL's common functions.
*
* DEPENDENCIES:
* mvIALCommon.h.
*
*******************************************************************************/
/* includes */
#include "mvOs.h"
#include "mvScsiAtaLayer.h"
#include "mvIALCommon.h"
#include "mvIALCommonUtils.h"
#include "mvStorageDev.h"
/* defines */
#undef DISABLE_PM_SCC
#undef ALLOW_NCQ
/* typedefs */
/*Static functions*/
static MV_BOOLEAN mvGetEDMAAllowedModes(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
MV_SAL_ADAPTER_EXTENSION *pScsiAdapterExt,
MV_U8 channelIndex,
MV_BOOLEAN *TCQ,
MV_BOOLEAN *NCQ,
MV_U8 *queueDepth,
MV_U8 *numOfDrives);
static void mvFlushSCSICommandQueue(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
MV_U8 channelIndex);
static void mvAddToSCSICommandQueue(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
MV_U8 channelIndex,
MV_SATA_SCSI_CMD_BLOCK *Scb);
static MV_BOOLEAN mvAdapterStateMachine(
MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
MV_SAL_ADAPTER_EXTENSION *scsiAdapterExt);
static MV_BOOLEAN mvChannelStateMachine(
MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
MV_U8 channelIndex,
MV_SAL_ADAPTER_EXTENSION *scsiAdapterExt);
static void mvSetChannelState(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
MV_U8 channelIndex,
MV_CHANNEL_STATE state);
/*PM related*/
static MV_BOOLEAN mvPMCommandCompletionCB(MV_SATA_ADAPTER *pSataAdapter,
MV_U8 channelIndex,
MV_COMPLETION_TYPE comp_type,
MV_VOID_PTR commandId,
MV_U16 responseFlags,
MV_U32 timeStamp,
MV_STORAGE_DEVICE_REGISTERS *registerStruct);
static MV_BOOLEAN mvQueuePMAccessRegisterCommand(
MV_IAL_COMMON_ADAPTER_EXTENSION* ialExt,
MV_U8 channelIndex,
MV_U8 PMPort,
MV_U8 PMReg,
MV_U32 Value,
MV_BOOLEAN isRead);
static MV_BOOLEAN mvPMEstablishSataComm(
MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
MV_U8 channelIndex);
static MV_BOOLEAN mvPMCheckForConnectedDevices(
MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
MV_U8 channelIndex,
MV_BOOLEAN* bIsChannelReady);
static MV_BOOLEAN mvInitPMDevice(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
MV_U8 channelIndex,
MV_SAL_ADAPTER_EXTENSION *scsiAdapterExt,
MV_BOOLEAN* bIsChannelReady,
MV_BOOLEAN* isDeviceReconnected,
MV_BOOLEAN* bPMErrorDetected);
static MV_BOOLEAN mvPMEnableCommStatusChangeBits(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
MV_U8 channelIndex,
MV_BOOLEAN enable);
static MV_BOOLEAN mvPMEnableAsyncNotify(
MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
MV_U8 channelIndex);
static void mvCheckPMForError(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
MV_U8 channelIndex);
/*End PM related*/
static MV_BOOLEAN mvStartChannelInit(MV_SATA_ADAPTER *pSataAdapter,
MV_U8 channelIndex,
MV_SAL_ADAPTER_EXTENSION *scsiAdapterExt,
MV_BOOLEAN *isChannelReady);
static MV_BOOLEAN mvChannelSRSTFinished(MV_SATA_ADAPTER *pSataAdapter,
MV_SATA_CHANNEL *pSataChannel,
MV_U8 channelIndex,
MV_SAL_ADAPTER_EXTENSION *scsiAdapterExt,
MV_BOOLEAN* bIsChannelReady,
MV_BOOLEAN* bFatalError);
static MV_BOOLEAN mvConfigChannelQueuingMode(
MV_IAL_COMMON_ADAPTER_EXTENSION* ialExt,
MV_U8 channelIndex,
MV_SAL_ADAPTER_EXTENSION *scsiAdapterExt);
static MV_BOOLEAN mvConfigChannelDMA(
MV_IAL_COMMON_ADAPTER_EXTENSION* ialExt,
MV_U8 channelIndex,
MV_SAL_ADAPTER_EXTENSION *scsiAdapterExt);
static void mvSetChannelTimer(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
MV_U8 channelIndex,
MV_U32 timeout);
static void mvDecrementChannelTimer(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
MV_U8 channelIndex);
static MV_BOOLEAN mvIsChannelTimerExpired(
MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
MV_U8 channelIndex);
/*Channel state machine*/
static MV_BOOLEAN mvChannelNotConnectedStateHandler(
MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
MV_U8 channelIndex,
MV_SAL_ADAPTER_EXTENSION *scsiAdapterExt);
static MV_BOOLEAN mvChannelConnectedStateHandler(
MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
MV_U8 channelIndex,
MV_SAL_ADAPTER_EXTENSION *scsiAdapterExt);
MV_BOOLEAN mvChannelInSrstStateHandler(
MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
MV_U8 channelIndex,
MV_SAL_ADAPTER_EXTENSION *scsiAdapterExt);
static MV_BOOLEAN mvChannelPMStaggeredSpinUpStateHandler(
MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
MV_U8 channelIndex,
MV_SAL_ADAPTER_EXTENSION *scsiAdapterExt);
static MV_BOOLEAN mvChannelPMSrstDeviceStateHandler(
MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
MV_U8 channelIndex,
MV_SAL_ADAPTER_EXTENSION *scsiAdapterExt);
static MV_BOOLEAN mvChannelReadyStateHandler(
MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
MV_U8 channelIndex);
static MV_BOOLEAN mvChannelPMHotPlugStateHandler(
MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
MV_U8 channelIndex,
MV_SAL_ADAPTER_EXTENSION *scsiAdapterExt);
#ifdef DISABLE_PM_SCC
MV_BOOLEAN mvPMDisableSSC(MV_SATA_ADAPTER *pSataAdapter, MV_U8 channelIndex);
#endif
#ifdef ALLOW_NCQ
MV_BOOLEAN mvPMEnableLocking(MV_SATA_ADAPTER *pSataAdapter, MV_U8 channelIndex);
#endif
/*Public functions*/
/*******************************************************************************
* mvAdapterStartInitialization - start adapter initialization
*
* DESCRIPTION:
* Starts adapter initialization after driver load.
* State - machine related data structure is initialized for adapter
* and its channels. Begin staggered spin-up.
* Adapter state is changed to ADAPTER_READY.
* INPUT:
* pAdapter - pointer to the adapter data structure.
* scsiAdapterExt - SCSI to ATA layer adapter extension data structure
* OUTPUT:
* None.
*
* RETURN:
* MV_TRUE on success
* MV_FALSE on error
*
*******************************************************************************/
MV_BOOLEAN mvAdapterStartInitialization(MV_SATA_ADAPTER *pSataAdapter,
MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
MV_SAL_ADAPTER_EXTENSION *scsiAdapterExt)
{
MV_U8 channelIndex;
ialExt->pSataAdapter = pSataAdapter;
ialExt->adapterState = ADAPTER_INITIALIZING;
for (channelIndex = 0; channelIndex < MV_SATA_CHANNELS_NUM; channelIndex++)
{
ialExt->channelState[channelIndex] = CHANNEL_NOT_CONNECTED;
ialExt->IALChannelExt[channelIndex].SRSTTimerThreshold = 0;
ialExt->IALChannelExt[channelIndex].SRSTTimerValue = 0;
ialExt->IALChannelExt[channelIndex].IALChannelPendingCmdQueue = NULL;
ialExt->IALChannelExt[channelIndex].completionError = MV_FALSE;
ialExt->IALChannelExt[channelIndex].pmRegAccessInProgress = MV_FALSE;
ialExt->IALChannelExt[channelIndex].devInSRST =
MV_SATA_PM_CONTROL_PORT + 1;
ialExt->IALChannelExt[channelIndex].PMdevsToInit = 0;
ialExt->IALChannelExt[channelIndex].PMnumberOfPorts = 0;
ialExt->IALChannelExt[channelIndex].pmAccessType = 0;
ialExt->IALChannelExt[channelIndex].pmReg = 0;
ialExt->IALChannelExt[channelIndex].pmAsyncNotifyEnabled = MV_FALSE;
}
return mvAdapterStateMachine(ialExt, scsiAdapterExt);
}
/*******************************************************************************
* mvRestartChannel - restart specific channel
*
* DESCRIPTION:
* The function is used in channel hot-plug to restart the channel
* initialization sequence. The channel stated is changed to
* CHANNEL_CONNECTED and any pending command in software queue are flushed
* INPUT:
* pAdapter - pointer to the adapter data structure.
* channelIndex - channel number
* scsiAdapterExt - SCSI to ATA layer adapter extension data structure
* bBusReset - MV_TRUE if the faunction is called because of bus reset,
* MV_FALSE otherwise
* OUTPUT:
* None.
*
* RETURN:
* MV_TRUE on success
* MV_FALSE on error
*
*******************************************************************************/
void mvRestartChannel(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
MV_U8 channelIndex,
MV_SAL_ADAPTER_EXTENSION *scsiAdapterExt,
MV_BOOLEAN bBusReset)
{
MV_SATA_ADAPTER *pSataAdapter = ialExt->pSataAdapter;
MV_BOOLEAN bBusChangeNotify = MV_FALSE;
mvSataScsiSetDriveReady(scsiAdapterExt,
channelIndex, 0xFF, MV_FALSE);
if (pSataAdapter->sataChannel[channelIndex] != NULL)
{
if (mvStorageDevGetDeviceType(pSataAdapter,channelIndex)
== MV_SATA_DEVICE_TYPE_PM)
{
bBusChangeNotify = MV_TRUE;
}
mvSataDisableChannelDma(pSataAdapter, channelIndex);
mvSataFlushDmaQueue (pSataAdapter, channelIndex,
MV_FLUSH_TYPE_CALLBACK);
}
mvFlushSCSICommandQueue(ialExt, channelIndex);
ialExt->IALChannelExt[channelIndex].SRSTTimerThreshold = 0;
ialExt->IALChannelExt[channelIndex].SRSTTimerValue = 0;
if (pSataAdapter->sataChannel[channelIndex] != NULL)
{
mvSataRemoveChannel(pSataAdapter,channelIndex);
IALReleaseChannel(pSataAdapter, channelIndex);
pSataAdapter->sataChannel[channelIndex] = NULL;
}
ialExt->channelState[channelIndex] = CHANNEL_CONNECTED;
if (bBusReset == MV_TRUE)
{
if (bBusChangeNotify == MV_TRUE)
{
/*Notify about bus change*/
IALBusChangeNotify(pSataAdapter, channelIndex);
}
}
else
{
/*Notify about bus change*/
IALBusChangeNotify(pSataAdapter, channelIndex);
}
}
/*******************************************************************************
* mvPMHotPlugDetected - restart specific channel
*
* DESCRIPTION:
* The function is used in PM hot-plug to wait for empty EDMA command queue
* and then restart the channel initialization sequence.
* The channel stated is changed to CHANNEL_PM_HOT_PLUG if there are any
* pending command in EDMA queue
* INPUT:
* pAdapter - pointer to the adapter data structure.
* channelIndex - channel number
* OUTPUT:
* None.
*
* RETURN:
* None
*
*******************************************************************************/
void mvPMHotPlugDetected(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
MV_U8 channelIndex,
MV_SAL_ADAPTER_EXTENSION *scsiAdapterExt)
{
if (ialExt->channelState[channelIndex] == CHANNEL_NOT_CONNECTED ||
ialExt->channelState[channelIndex] == CHANNEL_CONNECTED ||
ialExt->channelState[channelIndex] == CHANNEL_IN_SRST)
{
return;
}
mvSataDisableChannelDma(ialExt->pSataAdapter, channelIndex);
mvSataFlushDmaQueue (ialExt->pSataAdapter,
channelIndex, MV_FLUSH_TYPE_CALLBACK);
mvSataChannelHardReset(ialExt->pSataAdapter, channelIndex);
mvRestartChannel(ialExt, channelIndex, scsiAdapterExt, MV_FALSE);
}
/*******************************************************************************
* mvStopChannel - stop channel
*
* DESCRIPTION:
* The function is used when the channel is unplugged.
* The channel stated is changed to CHANNEL_NOT_CONNECTED
* until further connection.
* INPUT:
* pAdapter - pointer to the adapter data structure.
* channelIndex - channel number
* OUTPUT:
* None.
*
* RETURN:
* None
*******************************************************************************/
void mvStopChannel(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
MV_U8 channelIndex,
MV_SAL_ADAPTER_EXTENSION *scsiAdapterExt)
{
MV_SATA_ADAPTER *pSataAdapter = ialExt->pSataAdapter;
mvSataScsiSetDriveReady(scsiAdapterExt, channelIndex, 0xFF, MV_FALSE);
mvSetChannelState(ialExt, channelIndex, CHANNEL_NOT_CONNECTED);
if (pSataAdapter->sataChannel[channelIndex] != NULL)
{
mvSataDisableChannelDma(ialExt->pSataAdapter, channelIndex);
mvSataFlushDmaQueue (ialExt->pSataAdapter, channelIndex,
MV_FLUSH_TYPE_CALLBACK);
}
mvFlushSCSICommandQueue(ialExt, channelIndex);
if (pSataAdapter->sataChannel[channelIndex] != NULL)
{
mvSataRemoveChannel(pSataAdapter,channelIndex);
IALReleaseChannel(pSataAdapter, channelIndex);
}
pSataAdapter->sataChannel[channelIndex] = NULL;
/*Notify about bus change*/
IALBusChangeNotify(pSataAdapter, channelIndex);
}
/*******************************************************************************
* mvExecuteScsiCommand - execute SCSI command
*
* DESCRIPTION:
* IAL common layer wrapper of mvSataExecuteScsiCommand function.
* If either the adapter state is either other than ADAPTER_READY
* or the channel is connected but channel state is not CHANNEL_READY,
* the current SCSI command is queued in channel's SCSI commands
* software queue until channel initialization sequence completed.
* If channel is found in CHANNEL ready state the SCSI command is passed to
* SCSI ATA translation layer.
* INPUT:
* pScb - SCSI command block structure.
*
* OUTPUT:
* None.
*
* RETURN:
* Return MV_SCSI_COMMAND_STATUS_COMPLETED if the command has been added
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -