📄 mvsata.c
字号:
break;
default: /* never reached */
break;
}
}
static MV_BOOLEAN transferPIOData(MV_SATA_CHANNEL *pSataChannel,
MV_NONE_UDMA_COMMAND_PARAMS *pNoneUdmaCommandParams)
{
MV_U32 i;
mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG|MV_DEBUG_NON_UDMA_COMMAND,
"%d %d: xfer data for PIO Data command.count %d\n",
pSataChannel->mvSataAdapter->adapterId,
pSataChannel->channelNumber, pNoneUdmaCommandParams->count);
switch (pNoneUdmaCommandParams->protocolType)
{
case MV_NON_UDMA_PROTOCOL_PIO_DATA_OUT:
for (i = 0; i < 256; i++)
{
if (pNoneUdmaCommandParams->count == 0)
{
return MV_TRUE;
}
pNoneUdmaCommandParams->count--;
MV_REG_WRITE_WORD(pSataChannel->mvSataAdapter->adapterIoBaseAddress,
pSataChannel->eDmaRegsOffset +
MV_ATA_DEVICE_PIO_DATA_REG_OFFSET,
*pNoneUdmaCommandParams->bufPtr++);
}
break;
case MV_NON_UDMA_PROTOCOL_PIO_DATA_IN:
for (i = 0; i < 256; i++)
{
if (pNoneUdmaCommandParams->count == 0)
{
return MV_TRUE;
}
pNoneUdmaCommandParams->count--;
*pNoneUdmaCommandParams->bufPtr++ =
MV_REG_READ_WORD(pSataChannel->mvSataAdapter->adapterIoBaseAddress,
pSataChannel->eDmaRegsOffset +
MV_ATA_DEVICE_PIO_DATA_REG_OFFSET);
}
break;
case MV_NON_UDMA_PROTOCOL_NON_DATA:
mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%d %d: in xfer data "
"PIO command is None Data \n",
pSataChannel->mvSataAdapter->adapterId,
pSataChannel->channelNumber);
return MV_FALSE;
}
return MV_TRUE;
}
static void completePIOCommand(MV_SATA_CHANNEL *pSataChannel,
MV_QUEUED_COMMAND_ENTRY *pCommandEntry,
MV_BOOLEAN failed)
{
MV_COMPLETION_TYPE compType = MV_COMPLETION_TYPE_NORMAL;
MV_STORAGE_DEVICE_REGISTERS deviceRegs;
MV_NONE_UDMA_COMMAND_PARAMS *pParams =
&pCommandEntry->commandInfo.commandParams.NoneUdmaCommand;
dumpAtaDeviceRegisters(pSataChannel->mvSataAdapter,
pSataChannel->channelNumber, pParams->isEXT,
&deviceRegs);
if (failed == MV_TRUE)
{
mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%d %d: PIO Command completed "
"with error\n", pSataChannel->mvSataAdapter->adapterId,
pSataChannel->channelNumber);
compType = MV_COMPLETION_TYPE_ERROR;
pSataChannel->queueCommandsEnabled = MV_FALSE;
}
else
{
mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG|MV_DEBUG_NON_UDMA_COMMAND,
"%d %d: PIO Command completed successfully\n",
pSataChannel->mvSataAdapter->adapterId,
pSataChannel->channelNumber);
}
pParams->callBack(pSataChannel->mvSataAdapter, pSataChannel->channelNumber,
compType, pParams->commandId, 0, 0, &deviceRegs);
removeCommand(pSataChannel,pCommandEntry);
if ((failed == MV_TRUE) && (mvAutoFlushOnError == MV_TRUE))
{
_doAutoFlush(pSataChannel);
}
if (pSataChannel->commandsQueueHead == NULL)
{
mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG|MV_DEBUG_NON_UDMA_COMMAND,
"%d %d: Commands queue is empty\n",
pSataChannel->mvSataAdapter->adapterId,
pSataChannel->channelNumber);
return;
}
if (pSataChannel->commandsQueueHead->commandInfo.type ==
MV_QUEUED_COMMAND_TYPE_NONE_UDMA)
{
mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG|MV_DEBUG_NON_UDMA_COMMAND,
"%d %d: Next Command is PIO\n",
pSataChannel->mvSataAdapter->adapterId,
pSataChannel->channelNumber);
if (pSataChannel->PMSupported == MV_TRUE)
{
_setActivePMPort(pSataChannel,
pSataChannel->commandsQueueHead->commandInfo.PMPort);
}
if (sendNoneUdmaCommand(pSataChannel,
pSataChannel->commandsQueueHead) == MV_FALSE)
{
completePIOCommand(pSataChannel, pSataChannel->commandsQueueHead,
MV_FALSE);
}
}
else
{
MV_QUEUED_COMMAND_ENTRY *pEntry;
mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG|MV_DEBUG_NON_UDMA_COMMAND,
"%d %d: Next Command is UDMA\n",
pSataChannel->mvSataAdapter->adapterId,
pSataChannel->channelNumber);
activateEdma(pSataChannel->mvSataAdapter,pSataChannel->channelNumber);
pEntry = pSataChannel->commandsQueueHead;
while ((pEntry != NULL) &&
(pEntry->commandInfo.type == MV_QUEUED_COMMAND_TYPE_UDMA))
{
EdmaReqQueueInsert(pSataChannel, pEntry,
&pEntry->commandInfo.commandParams.udmaCommand);
pEntry = pEntry->next;
}
}
}
/*******************************************************************************
* resetEdmaChannel - resets the channel data stucture and EDMA registers
*
*
* DESCRIPTION:
* this function resets the low level EDMA fields of Sata channel data
* structure and initialize the EDMA register accourdingly
*
* INPUT:
* *pSataChannel - pointer to the Sata channel data structure
*
* RETURN:
* MV_TRUE on success, MV_FALSE otherwise.
*
* COMMENTS:
* this function assumes that the channel semaphore is locked
*
*******************************************************************************/
static MV_BOOLEAN resetEdmaChannel(MV_SATA_CHANNEL *pSataChannel)
{
MV_BUS_ADDR_T ioBaseAddr =
pSataChannel->mvSataAdapter->adapterIoBaseAddress;
MV_U32 eDmaRegsOffset = pSataChannel->eDmaRegsOffset;
int i;
mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, "%d %d: resetEdmaChannel\n",
pSataChannel->mvSataAdapter->adapterId,
pSataChannel->channelNumber);
if (MV_REG_READ_DWORD(ioBaseAddr, eDmaRegsOffset +
MV_EDMA_COMMAND_REG_OFFSET) &
MV_EDMA_COMMAND_HARD_RST_MASK)
{
MV_REG_WRITE_DWORD(ioBaseAddr, eDmaRegsOffset +
MV_EDMA_COMMAND_REG_OFFSET,
MV_EDMA_COMMAND_DISABLE_MASK);
MV_REG_READ_DWORD(ioBaseAddr, eDmaRegsOffset +
MV_EDMA_COMMAND_REG_OFFSET);
mvMicroSecondsDelay(pSataChannel->mvSataAdapter,
MV_HARD_RESET_WAIT_NEGATE);
_fixPhyParams(pSataChannel->mvSataAdapter, pSataChannel->channelNumber);
}
else
{
MV_REG_WRITE_DWORD(ioBaseAddr, eDmaRegsOffset +
MV_EDMA_COMMAND_REG_OFFSET,
MV_EDMA_COMMAND_DISABLE_MASK);
}
pSataChannel->outstandingCommands = 0;
pSataChannel->noneUdmaOutstandingCommands = 0;
pSataChannel->EdmaQueuedCommands = 0;
pSataChannel->reqInPtr = 0;
pSataChannel->rspOutPtr = 0;
pSataChannel->EdmaActive = MV_FALSE;
/* init free entries stack*/
pSataChannel->freeIDsNum = MV_SATA_SW_QUEUE_SIZE;
for (i = 0; i < MV_SATA_SW_QUEUE_SIZE; i++)
{
pSataChannel->freeIDsStack[i] = MV_SATA_SW_QUEUE_SIZE - 1 - i;
pSataChannel->commandsQueue[i].isFreeEntry = MV_TRUE;
}
pSataChannel->commandsQueueHead = NULL;
pSataChannel->commandsQueueTail = NULL;
pSataChannel->queueCommandsEnabled = MV_FALSE;
#ifdef MV_SATA_C2C_COMM
/* C2C */
pSataChannel->C2CmodeEnabled = MV_FALSE;
#endif
MV_REG_WRITE_DWORD(ioBaseAddr, eDmaRegsOffset +
MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET, 0);
/* enable connect/disconnet and selfDisable, the rest of errors will */
/* eventually cause selfDisable interrupt */
if (pSataChannel->mvSataAdapter->sataAdapterGeneration == MV_SATA_GEN_I)
{
MV_REG_WRITE_DWORD(ioBaseAddr, eDmaRegsOffset +
MV_EDMA_INTERRUPT_ERROR_MASK_REG_OFFSET,
MV_BIT8 | MV_BIT4 | MV_BIT3);
}
else
{
MV_REG_WRITE_DWORD(ioBaseAddr, eDmaRegsOffset +
MV_EDMA_INTERRUPT_ERROR_MASK_REG_OFFSET,
MV_BIT8 | MV_BIT7 | MV_BIT4 | MV_BIT3);
}
MV_REG_WRITE_DWORD(ioBaseAddr, eDmaRegsOffset +
MV_EDMA_REQUEST_Q_BAH_REG_OFFSET,
pSataChannel->requestQueuePciHiAddress);
MV_REG_WRITE_DWORD(ioBaseAddr, eDmaRegsOffset +
MV_EDMA_REQUEST_Q_INP_REG_OFFSET,
pSataChannel->requestQueuePciLowAddress &
MV_EDMA_REQUEST_Q_BA_MASK);
MV_REG_WRITE_DWORD(ioBaseAddr, eDmaRegsOffset +
MV_EDMA_REQUEST_Q_OUTP_REG_OFFSET, 0);
MV_REG_WRITE_DWORD(ioBaseAddr, eDmaRegsOffset +
MV_EDMA_RESPONSE_Q_BAH_REG_OFFSET,
pSataChannel->responseQueuePciHiAddress);
MV_REG_WRITE_DWORD(ioBaseAddr, eDmaRegsOffset +
MV_EDMA_RESPONSE_Q_INP_REG_OFFSET, 0);
MV_REG_WRITE_DWORD(ioBaseAddr, eDmaRegsOffset +
MV_EDMA_RESPONSE_Q_OUTP_REG_OFFSET,
pSataChannel->responseQueuePciLowAddress &
MV_EDMA_RESPONSE_Q_BA_MASK);
return MV_TRUE;
}
static void flushDmaQueue(MV_SATA_CHANNEL *pSataChannel,MV_FLUSH_TYPE flushType,
MV_COMPLETION_TYPE completionType, MV_U16 eDmaCause)
{
mvSataCommandCompletionCallBack_t callBackFunc;
int i;
mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%d %d: Flush DMA, type=%s, commands"
" %d (on EDMA %d)\n", pSataChannel->mvSataAdapter->adapterId,
pSataChannel->channelNumber,
(flushType==MV_FLUSH_TYPE_CALLBACK)?"CALLBACK":"NONE",
pSataChannel->outstandingCommands,pSataChannel->EdmaQueuedCommands);
if (flushType == MV_FLUSH_TYPE_CALLBACK)
{
for (i=0;i < MV_SATA_SW_QUEUE_SIZE; i++)
{
if (pSataChannel->commandsQueue[i].isFreeEntry == MV_FALSE)
{
MV_STORAGE_DEVICE_REGISTERS deviceRegisters;
MV_BOOLEAN isEXT;
MV_VOID_PTR commandId;
if (pSataChannel->commandsQueue[i].commandInfo.type == MV_QUEUED_COMMAND_TYPE_NONE_UDMA)
{
isEXT = pSataChannel->commandsQueue[i].commandInfo.commandParams.NoneUdmaCommand.isEXT;
commandId = pSataChannel->commandsQueue[i].commandInfo.commandParams.NoneUdmaCommand.commandId;
callBackFunc = pSataChannel->commandsQueue[i].commandInfo.commandParams.NoneUdmaCommand.callBack;
}
else
{
isEXT = pSataChannel->commandsQueue[i].commandInfo.commandParams.udmaCommand.isEXT;
commandId = pSataChannel->commandsQueue[i].commandInfo.commandParams.udmaCommand.commandId;
callBackFunc = pSataChannel->commandsQueue[i].commandInfo.commandParams.udmaCommand.callBack;
}
dumpAtaDeviceRegisters(pSataChannel->mvSataAdapter,
pSataChannel->channelNumber, isEXT,
&deviceRegisters);
mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG|MV_DEBUG_ERROR,
"%d %d: Calling callBackFunc - command index %d at %p,"
" next %p, prev %p\n",
pSataChannel->mvSataAdapter->adapterId,
pSataChannel->channelNumber,
i,
&pSataChannel->commandsQueue[i],
pSataChannel->commandsQueue[i].next,
pSataChannel->commandsQueue[i].prev);
callBackFunc(pSataChannel->mvSataAdapter,
pSataChannel->channelNumber, completionType,
commandId, eDmaCause, 0, &deviceRegisters);
}
}
}
}
static void _fixPhyParams(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex)
{
/* Set unit 0 or 1 */
MV_U8 sataUnit = (channelIndex & MV_BIT2) >> 2;
/* Set port 0-3 */
MV_U8 port = channelIndex & (MV_BIT0 | MV_BIT1);
MV_U32 regVal;
if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_I)
{
if (pAdapter->implement50XXB0Workarounds == MV_TRUE)
{
/* Fix for 88SX50xx FEr SATA#12 */
/* Disable auto-power management*/
regVal = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
MV_SATAHC_REGS_BASE_OFFSET(sataUnit) +
MV_SATA_I_HC_LT_MODES_PORT_REG_OFFSET(port));
regVal |= MV_BIT19; /* disbale auto-power management*/
MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
MV_SATAHC_REGS_BASE_OFFSET(sataUnit) +
MV_SATA_I_HC_LT_MODES_PORT_REG_OFFSET(port),
regVal);
/* 88SX50xx FEr SATA#9*/
/*Fix squelch threshold*/
regVal = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
MV_SATAHC_REGS_BASE_OFFSET(sataUnit) +
MV_SATA_I_HC_PHY_CONTROL_BRIDGE_PORT_OFFSET(port));
regVal &= ~0x3;
regVal |= 0x1;
MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
MV_SATAHC_REGS_BASE_OFFSET(sataUnit) +
MV_SATA_I_HC_PHY_CONTROL_BRIDGE_PORT_OFFSET(port),
regVal);
}
/* Revert values of pre-emphasis and signal amps to the saved ones */
{
regVal = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
MV_SATAHC_REGS_BASE_OFFSET(sataUnit) +
MV_SATA_I_HC_PHY_MODE_BRIDGE_PORT_REG_OFFSET(port));
regVal &= ~MV_SATA_I_PHY_MODE_AMP_MASK;
regVal |= (pAdapter->signalAmps[channelIndex] << MV_SATA_I_PHY_MODE_AMP_OFFSET) &
MV_SATA_I_PHY_MODE_AMP_MASK;
regVal &= ~MV_SATA_I_PHY_MODE_PRE_MASK;
regVal |= (pAdapter->pre[channelIndex] << MV_SATA_I_PHY_MODE_PRE_OFFSET) &
MV_SATA_I_PHY_MODE_PRE_MASK;
MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
MV_SATAHC_REGS_BASE_OFFSET(sataUnit) +
MV_SATA_I_HC_PHY_MODE_BRIDGE_PORT_REG_OFFSET(port),
regVal);
}
}
if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_II)
{
MV_U32 phyMode2Offset = getEdmaRegOffset(channelIndex) +
MV_SATA_II_PHY_MODE_2_REG_OFFSET;
/* Fix values in phyMode 4 register.*/
/* 88SX60x1 FEr SATA#10 */
if ((pAdapter->implement60X1A1Workarounds == MV_TRUE) ||
(pAdapter->implement60X1B0Workarounds == MV_TRUE))
{
MV_U32 phyMode4Value;
MV_U32 tempRegOffset, tempRe
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -