📄 mvsata.c
字号:
compType, pUdmaCommandParams->commandId,
eDmaCause, response.timeStamp, &deviceRegs);
removeCommand(pSataChannel,pCommandEntry);
if (pSataChannel->queueCommandsEnabled == MV_FALSE)
{
mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG|MV_DEBUG_UDMA_COMMAND,
"%d %d: Commands queuing is disabled\n",
pSataChannel->mvSataAdapter->adapterId,
pSataChannel->channelNumber);
return;
}
if (pSataChannel->commandsQueueHead == NULL)
{
mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG|MV_DEBUG_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_UDMA_COMMAND,
"%d %d: Next Command is PIO\n",
pSataChannel->mvSataAdapter->adapterId,
pSataChannel->channelNumber);
deactivateEdma(pAdapter,channelIndex);
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
{
mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG|MV_DEBUG_UDMA_COMMAND,
"%d %d: Next Command is UDMA nothing to do\n",
pSataChannel->mvSataAdapter->adapterId,
pSataChannel->channelNumber);
}
}
}
#ifdef MV_SATA_C2C_COMM
/*******************************************************************************
* handleBmDmaInterrupt - handle DMA interrupt received for a given channel
*
* DESCRIPTION:
* This function is called when response interrupt is issued when C2C DMA
* completion event occurs.
*
* INPUT:
* pAdapter - pointer to the MV88SX50XX adapter data structure
* ioBaseAddr - adapter rbase address
* pSataChannel - SATA channel structure
* channelIndex - SATA channel index
* edmaError - if != zero then EDMA error happened.
*
* RETURN:
* None.
*
* COMMENTS:
* None
*
*******************************************************************************/
static void handleBmDMAInterrupt(MV_SATA_ADAPTER *pAdapter,
MV_BUS_ADDR_T ioBaseAddr,
MV_SATA_CHANNEL *pSataChannel,
MV_U8 channelIndex,
MV_U32 edmaError)
{
MV_U32 val;
MV_U32 eDmaErrorCause = 0;
mvOsSemTake(&pSataChannel->semaphore);
/*Reset BM dma*/
val = MV_REG_READ_DWORD (ioBaseAddr,
getEdmaRegOffset(channelIndex) +
MV_BMDMA_COMMAND_OFFSET);
val &= ~MV_BIT0;
MV_REG_WRITE_DWORD (ioBaseAddr,
getEdmaRegOffset(channelIndex) +
MV_BMDMA_COMMAND_OFFSET, val);
MV_REG_WRITE_DWORD(ioBaseAddr,
getEdmaRegOffset(channelIndex) +
MV_SATA_II_IF_CONTROL_REG_OFFSET,
0);
if (edmaError)
{
eDmaErrorCause = (MV_U16)MV_REG_READ_DWORD(ioBaseAddr,
getEdmaRegOffset(channelIndex) +
MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET);
}
mvOsSemRelease(&pSataChannel->semaphore);
if (pSataChannel->C2CCallback)
{
if (!edmaError)
{
pSataChannel->C2CCallback(pAdapter,
pSataChannel,
MV_C2C_BM_DMA_DONE,
0,
NULL);
}
else
{
if (eDmaErrorCause & (MV_BIT17 | MV_BIT26))
{
pSataChannel->C2CCallback(pAdapter,
pSataChannel,
MV_C2C_BM_DMA_ERROR,
0,
NULL);
}
if (eDmaErrorCause & (MV_BIT13 | MV_BIT21))
{
pSataChannel->C2CCallback(pAdapter,
pSataChannel,
MV_C2C_REGISTER_DEVICE_TO_HOST_FIS_ERROR,
0,
NULL);
}
}
}
}
#endif
/*******************************************************************************
* handleEdmaInterrupt - handle EDMA interrupt receivd for a given channel
*
* DESCRIPTION:
* this function called when response interrupt issuesed for a channel and it
* handles all EDMA responses.
*
* INPUT:
* *pAdapter - pointer to the MV88SX50XX adapter data structure
* sataUnit - the SATAHC unit this channel belongs to
* port - the port number of the channel
* rspInPtr - the value of eRPQIP of the channel
* responseDone - if != zero then responses received on this channel
* edmaError - if != zero then EDMA error happened.
*
* RETURN:
* None.
*
* COMMENTS:
* None.
*
*******************************************************************************/
static void handleEdmaInterrupt(MV_SATA_ADAPTER *pAdapter, MV_U8 sataUnit,
MV_U8 port,MV_U32 rspInPtr, MV_U32 responseDone,
MV_U32 edmaError, MV_U32 unitCause)
{
MV_U32 rspOutPtr;
MV_U8 channelIndex;
MV_BUS_ADDR_T ioBaseAddr = pAdapter->adapterIoBaseAddress;
MV_U32 eDmaRegsOffset;
MV_SATA_CHANNEL *pSataChannel;
MV_U32 eDmaErrorCause = 0;
MV_BOOLEAN forceAutoFlush = MV_FALSE;
channelIndex = MV_CHANNEL_INDEX(sataUnit, port);
pSataChannel = pAdapter->sataChannel[channelIndex];
if (responseDone && (pSataChannel != NULL))/* port Done*/
{
mvOsSemTake(&pSataChannel->semaphore);
#ifdef MV_SATA_C2C_COMM
if (MV_FALSE == pSataChannel->C2CmodeEnabled)
{
#endif
eDmaRegsOffset = pSataChannel->eDmaRegsOffset;
rspOutPtr = pSataChannel->rspOutPtr;
/* here we should update the response out pointer though we didn't*/
/* handled the new responses, these response entries will not be */
/* accessed again by the EDMA sinse the number of queued commands */
/* (outstandingCommands) will be updated only after we handle each*/
/* response entry */
MV_REG_WRITE_DWORD(ioBaseAddr, eDmaRegsOffset +
MV_EDMA_RESPONSE_Q_OUTP_REG_OFFSET,
pSataChannel->responseQueuePciLowAddress |
(rspInPtr << MV_EDMA_RESPONSE_Q_OUTP_OFFSET));
while (rspOutPtr != rspInPtr)
{
handleEdmaResponse(pAdapter, channelIndex,
&(pSataChannel->responseQueue[rspOutPtr]));
rspOutPtr++;
rspOutPtr &= MV_EDMA_QUEUE_MASK;
}
/*
* Check if queueCommandsEnabled flag is disabled.
* If so, then an error has occured and auto flush must be triggered.
* Basically it is enough to trigger auto flush upon edmaError flag,
* but since edmaError is set before handleEdmaResponse is called
* there could be a racing condition between the time edmaError is checked
* and the response queue is checked.
* The racing condition is that an error does not occur when setting
* edmaError to MV_FALSE, but in handlEdmaResponse, the hardware
* has completed a command with error.
* The racing condition will complete the error command (through callback)
* but will prevent the auto flush of all outstanding commands.
*/
if (pSataChannel->queueCommandsEnabled == MV_FALSE)
{
forceAutoFlush = MV_TRUE;
}
pSataChannel->rspOutPtr = rspOutPtr;
mvOsSemRelease(&pSataChannel->semaphore);
#ifdef MV_SATA_C2C_COMM
}
else
{
mvOsSemRelease(&pSataChannel->semaphore);
handleBmDMAInterrupt(pAdapter,
ioBaseAddr,
pSataChannel,
channelIndex,
edmaError);
}
#endif
}
if ((edmaError) || (forceAutoFlush == MV_TRUE)) /* EDMA error interrupt*/
{
eDmaErrorCause = MV_REG_READ_DWORD(ioBaseAddr,
getEdmaRegOffset(channelIndex) +
MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET);
mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR | MV_DEBUG_INTERRUPTS,
"%d %d: Edma Error Reg 0x%x\n", pAdapter->adapterId,
channelIndex, MV_REG_READ_DWORD(ioBaseAddr,
getEdmaRegOffset(channelIndex) +
MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET));
/* clear the channel's error cause register */
MV_REG_WRITE_DWORD(ioBaseAddr,
getEdmaRegOffset(channelIndex) +
MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET,
~eDmaErrorCause);
if (MV_REG_READ_DWORD(ioBaseAddr,
getEdmaRegOffset(channelIndex) +
MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET))
{
mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR | MV_DEBUG_INTERRUPTS,
"%d %d: Edma Error Reg 0x%x still set!!!!!!!!\n",
pAdapter->adapterId, channelIndex,
MV_REG_READ_DWORD(ioBaseAddr,
getEdmaRegOffset(channelIndex) +
MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET));
if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_II)
{
/*wait 20ms till diconnect/connect interrupts finish*/
mvMicroSecondsDelay(pAdapter, 20000);
eDmaErrorCause |= MV_REG_READ_DWORD(ioBaseAddr,
getEdmaRegOffset(channelIndex) +
MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET);
MV_REG_WRITE_DWORD(ioBaseAddr,
getEdmaRegOffset(channelIndex) +
MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET,
~eDmaErrorCause);
}
}
/* dump in case any kind of parity error*/
if (eDmaErrorCause & (MV_BIT11 | MV_BIT10 | MV_BIT9 | MV_BIT1 | MV_BIT0))
{
mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR," PARITY ERROR Detected\n");
_dumpPCIRegs(pAdapter);
_dumpEDMARegs(pAdapter,channelIndex);
_dumpChannelQueues(pAdapter,channelIndex);
}
if (eDmaErrorCause & MV_BIT3) /*device disconneted*/
{
if (pSataChannel)
{
mvOsSemTake(&pSataChannel->semaphore);
pSataChannel->queueCommandsEnabled = MV_FALSE;
pSataChannel->EdmaActive = MV_FALSE;
}
/* If disk is disconnected, then disable the activity LED */
if (pAdapter->implement50XXB1Workarounds == MV_TRUE ||
pAdapter->implement50XXB2Workarounds == MV_TRUE)
{
MV_U32 regVal1, regVal2;
/* First enable flash controller clocks*/
regVal1 = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
MV_PCI_REGS_OFFSET +
MV_PCI_EXPANSION_ROM_CONTROL_REG_OFFSET);
regVal1 |= (MV_BIT0);
MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
MV_PCI_REGS_OFFSET + MV_PCI_EXPANSION_ROM_CONTROL_REG_OFFSET,
regVal1);
regVal1 = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
MV_PCI_REGS_OFFSET +
MV_PCI_EXPANSION_ROM_CONTROL_REG_OFFSET);
/* Disable activity LEDs */
regVal2 = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
MV_FLASH_GPIO_PORT_CONTROL_OFFSET);
regVal2 |= (MV_BIT8 << channelIndex);
MV_REG_WRITE_DWORD (pAdapter->adapterIoBaseAddress,
MV_FLASH_GPIO_PORT_CONTROL_OFFSET,
regVal2);
regVal2 = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
MV_FLASH_GPIO_PORT_CONTROL_OFFSET);
/* Disable flash controller clocks */
regVal1 &= ~(MV_BIT0);
MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
MV_PCI_REGS_OFFSET + MV_PCI_EXPANSION_ROM_CONTROL_REG_OFFSET,
regVal1);
}
/* Fix for 88SX50XX FEr SATA#2 */
if ((pAdapter->implement50XXB0Workarounds == MV_TRUE)||
(pAdapter->implement50XXB1Workarounds == MV_TRUE) ||
(pAdapter->implement50XXB2Workarounds == MV_TRUE))
{
mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_INTERRUPTS,
"%d %d: Before Hard RESET Main Cause %x\n",
pAdapter->adapterId, channelIndex,
MV_REG_READ_DWORD(ioBaseAddr,
MV_MAIN_INTERRUPT_CAUSE_REG_OFFSET));
/* Hard Reset the channel so we can do re-connect*/
_channelHardReset(pAdapter, channelIndex);
mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_INTERRUPTS,
"%d %d: After Hard RESET Main Cause %x\n",
pAdapter->adapterId, channelIndex,
MV_REG_READ_DWORD(ioBaseAddr,
MV_MAIN_INTERRUPT_CAUSE_REG_OFFSET));
}
else
{
if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_II)
{
_channelHardReset(pAdapter, channelIndex);
_establishSataComm(pAdapter, channelIndex);
}
}
/* after calling mvSataNotify we can not be sure that the channel*/
/* data structure is still available so first we release the */
/* semaphore, after notifying the upper-layer with the disconnect*/
/* event, nothing else is done with that channel */
if (pSataChannel)
{
mvOsSemRelease(&pSataChannel->semaphore);
}
if (mvSataIsStorageDeviceConnected(pAdapter,channelIndex) == MV_FALSE)
{
pAdapter->mvSataEventNotify(pAdapter,
MV_EVENT_TYPE_SATA_CABLE,
MV_SATA_CABLE_EVENT_DISCONNECT,
channelIndex);
}
/* continue only if we have also a connect interrupt*/
if ((eDmaErrorCause & MV_BIT4) == 0)
{
return;
}
}
if (eDmaErrorCause & MV_BIT4) /*device conneted*/
{
/* Fix for 88SX50xx FEr SATA#2 */
if ((pAdapter->implement50XXB0Workarounds == MV_TRUE) ||
(pAdapter->implement50XXB1Workarounds == MV_TRUE) ||
(pAdapter->implement50XXB2Workarounds == MV_TRUE))
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -