📄 mvsata.c
字号:
_fixPhyParams(pAdapter, channelIndex);/*TBD*/
/* The following link re-establishment is due to non */
/* Marvell driven hard drives */
_establishSataComm(pAdapter, channelIndex);
_establishSataComm(pAdapter, channelIndex);
}
/* If disk is connected, then enable 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);
/* Enable 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);
}
if (mvSataIsStorageDeviceConnected(pAdapter,channelIndex) == MV_TRUE)
{
pAdapter->mvSataEventNotify(pAdapter, MV_EVENT_TYPE_SATA_CABLE,
MV_SATA_CABLE_EVENT_CONNECT,
channelIndex);
}
return;
}
/*PM hot plug*/
if ((pAdapter->sataAdapterGeneration == MV_SATA_GEN_II) &&
(eDmaErrorCause & MV_BIT8))
{
MV_U32 regVal1;
if (pSataChannel != NULL)
{
mvOsSemTake(&pSataChannel->semaphore);
}
regVal1 = MV_REG_READ_DWORD(ioBaseAddr,
getEdmaRegOffset(channelIndex) +
MV_SATA_II_IF_STATUS_REG_OFFSET);
/*Clear status*/
if ((regVal1 & (MV_BIT31 | MV_BIT30))||
(pAdapter->implement60X1A1Workarounds == MV_TRUE))
{
MV_U32 regVal2 = MV_REG_READ_DWORD(ioBaseAddr,
getEdmaRegOffset(channelIndex) +
MV_SATA_II_IF_CONTROL_REG_OFFSET);
regVal2 |= MV_BIT24;
MV_REG_WRITE_DWORD(ioBaseAddr,
getEdmaRegOffset(channelIndex) +
MV_SATA_II_IF_CONTROL_REG_OFFSET, regVal2);
}
if (pSataChannel != NULL)
{
mvOsSemRelease(&pSataChannel->semaphore);
}
if ((((regVal1 & MV_BIT30) == 0) &&
((regVal1 & MV_BIT31) == MV_BIT31)) ||
(pAdapter->implement60X1A1Workarounds == MV_TRUE))
{
mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_INTERRUPTS,
"%d %d: PM asynchronous notification interrupt.\n",
pAdapter->adapterId, channelIndex);
pAdapter->mvSataEventNotify(pAdapter, MV_EVENT_TYPE_SATA_CABLE,
MV_SATA_CABLE_EVENT_PM_HOT_PLUG,
channelIndex);
}
return;
}
if ((((pAdapter->sataAdapterGeneration == MV_SATA_GEN_I) && (eDmaErrorCause & MV_BIT8)) ||
((pAdapter->sataAdapterGeneration == MV_SATA_GEN_II) && (eDmaErrorCause & MV_BIT7)))
&&
(pSataChannel != NULL)) /* edma self disable */
{
mvOsSemTake(&pSataChannel->semaphore);
if (pSataChannel->EdmaActive == MV_TRUE) /* if no completion done */
{
/* with that error */
mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR |MV_DEBUG_INTERRUPTS,
"%d %d: Edma Interrupt received without completion\n",
pAdapter->adapterId, channelIndex);
pSataChannel->queueCommandsEnabled = MV_FALSE;
pSataChannel->EdmaActive = MV_FALSE;
handleEdmaFailedCommand(pAdapter, channelIndex,
(MV_U16)eDmaErrorCause);
}
if (mvAutoFlushOnError == MV_TRUE)
{
_doAutoFlush(pSataChannel);
}
mvOsSemRelease(&pSataChannel->semaphore);
}
}
}
#ifdef MV_SATA_C2C_COMM
/*******************************************************************************
* handleC2CInterrupt - channel 2 channel interrupt handler
*
*
* DESCRIPTION:
* Handles channel 2 channel interrupt (register device 2 host FIS) and
* convert ATA registers values to user specific 10 bytes message
*
* INPUT:
* pSataChannel - pointer to the Sata channel data structure
*
* RETURN:
* None
*
* COMMENTS:
* None
*
*******************************************************************************/
static void handleC2CInterrupt(MV_SATA_CHANNEL *pSataChannel)
{
MV_BUS_ADDR_T ioBaseAddr =
pSataChannel->mvSataAdapter->adapterIoBaseAddress;
MV_U32 eDmaRegsOffset = pSataChannel->eDmaRegsOffset;
MV_U8 port = pSataChannel->channelNumber & (MV_BIT0 | MV_BIT1);
MV_U8 sataUnit = (pSataChannel->channelNumber & MV_BIT2) >> 2;
MV_U8 ATAstatus;
MV_STORAGE_DEVICE_REGISTERS deviceRegs;
mvOsSemTake(&pSataChannel->semaphore);
MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset +
MV_ATA_DEVICE_ALTERNATE_REG_OFFSET);
ATAstatus = MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset +
MV_ATA_DEVICE_STATUS_REG_OFFSET);
/* clear DevInterrupt*/
MV_REG_WRITE_DWORD(ioBaseAddr, MV_SATAHC_REGS_BASE_OFFSET(sataUnit) +
MV_SATAHC_INTERRUPT_CAUSE_REG_OFFSET, ~(MV_BIT8 << port));
mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG|MV_DEBUG_NON_UDMA_COMMAND,
"%d %d: C2C Interrupt: status 0x%02x\n",
pSataChannel->mvSataAdapter->adapterId,
pSataChannel->channelNumber, ATAstatus);
dumpAtaDeviceRegisters(pSataChannel->mvSataAdapter,
pSataChannel->channelNumber,
MV_TRUE,
&deviceRegs);
mvOsSemRelease(&pSataChannel->semaphore);
if (pSataChannel->C2CCallback)
{
MV_U8 msg[MV_C2C_MESSAGE_SIZE];
msg[0] = deviceRegs.errorRegister;
msg[1] = deviceRegs.lbaLowRegister & 0xFF;
msg[2] = deviceRegs.lbaMidRegister & 0xFF;
msg[3] = deviceRegs.lbaHighRegister & 0xFF;
msg[4] = deviceRegs.deviceRegister;
msg[5] = deviceRegs.lbaLowRegister >> 8;
msg[6] = deviceRegs.lbaMidRegister >> 8;
msg[7] = deviceRegs.lbaHighRegister >> 8;
msg[8] = deviceRegs.sectorCountRegister & 0xFF;
msg[9] = deviceRegs.sectorCountRegister >> 8;
pSataChannel->C2CCallback(pSataChannel->mvSataAdapter,
pSataChannel,
MV_C2C_REGISTER_DEVICE_TO_HOST_FIS_DONE,
MV_C2C_MESSAGE_SIZE,
msg);
}
}
#endif
static void handleDeviceInterrupt(MV_SATA_ADAPTER *pAdapter, MV_U8 sataUnit,
MV_U8 port)
{
MV_SATA_CHANNEL *pSataChannel;
MV_QUEUED_COMMAND_ENTRY *pCommandEntry;
MV_U8 channelIndex;
channelIndex = MV_CHANNEL_INDEX(sataUnit, port);
mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG|MV_DEBUG_NON_UDMA_COMMAND,
"%d %d: SaDevInterrupt Received\n", pAdapter->adapterId,
channelIndex);
pSataChannel = pAdapter->sataChannel[channelIndex];
if (pSataChannel == NULL)
{
mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR|MV_DEBUG_NON_UDMA_COMMAND,
"%d %d: SaDevInterrupt Received for disconnected channel\n",
pAdapter->adapterId, channelIndex);
/* disable SaDevInterrupts from this channel */
disableSaDevInterrutps(pAdapter,channelIndex);
return;
}
#ifdef MV_SATA_C2C_COMM
/*handle channel 2 channel communication mode*/
if (pSataChannel->C2CmodeEnabled == MV_TRUE)
{
handleC2CInterrupt(pSataChannel);
return;
}
#endif
mvOsSemTake(&pSataChannel->semaphore);
/* clear interrupt */
pCommandEntry = pSataChannel->commandsQueueHead;
if (pCommandEntry == NULL)
{
mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR|MV_DEBUG_NON_UDMA_COMMAND,
"%d %d: SaDevInterrupt: No command is running!!!\n",
pAdapter->adapterId, channelIndex);
_dumpSataRegs(pAdapter, channelIndex);
/* disable SaDevInterrupts from this channel */
disableSaDevInterrutps(pAdapter,channelIndex);
mvOsSemRelease(&pSataChannel->semaphore);
return;
}
if ((pCommandEntry->isFreeEntry == MV_TRUE) ||
(pCommandEntry->commandInfo.type != MV_QUEUED_COMMAND_TYPE_NONE_UDMA))
{
if (pCommandEntry->isFreeEntry == MV_TRUE)
{
mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR|MV_DEBUG_NON_UDMA_COMMAND,
"%d %d: SaDevInterrupt: current command is free ???\n",
pAdapter->adapterId, channelIndex);
}
else
{
mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR|MV_DEBUG_NON_UDMA_COMMAND,
"%d %d: SaDevInterrupt: current command is Not PIO ???\n",
pAdapter->adapterId, channelIndex);
}
/* disable SaDevInterrupts from this channel */
disableSaDevInterrutps(pAdapter,channelIndex);
mvOsSemRelease(&pSataChannel->semaphore);
return;
}
handlePIOInterrupt(pSataChannel, pCommandEntry);
mvOsSemRelease(&pSataChannel->semaphore);
}
static void handlePIOInterrupt(MV_SATA_CHANNEL *pSataChannel,
MV_QUEUED_COMMAND_ENTRY *pCommandEntry)
{
MV_BUS_ADDR_T ioBaseAddr = pSataChannel->mvSataAdapter->adapterIoBaseAddress;
MV_U32 eDmaRegsOffset = pSataChannel->eDmaRegsOffset;
MV_U8 port = pSataChannel->channelNumber & (MV_BIT0 | MV_BIT1);
MV_U8 sataUnit = (pSataChannel->channelNumber & MV_BIT2) >> 2;
MV_U8 ATAstatus;
MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset +
MV_ATA_DEVICE_ALTERNATE_REG_OFFSET);
ATAstatus = MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset +
MV_ATA_DEVICE_STATUS_REG_OFFSET);
/* clear DevInterrupt*/
MV_REG_WRITE_DWORD(ioBaseAddr, MV_SATAHC_REGS_BASE_OFFSET(sataUnit) +
MV_SATAHC_INTERRUPT_CAUSE_REG_OFFSET, ~(MV_BIT8 << port));
mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG|MV_DEBUG_NON_UDMA_COMMAND,
"%d %d: PIO Interrupt: cmd 0x%02X, type %d. status 0x%02x\n",
pSataChannel->mvSataAdapter->adapterId,
pSataChannel->channelNumber,
pCommandEntry->commandInfo.commandParams.NoneUdmaCommand.command,
pCommandEntry->commandInfo.commandParams.NoneUdmaCommand.protocolType,
ATAstatus);
if (ATAstatus & MV_ATA_BUSY_STATUS)
{
if (pSataChannel->mvSataAdapter->sataAdapterGeneration == MV_SATA_GEN_I)
{
mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%d %d: "
"PIO Interrupt: drive is BUSY!!!! status 0x%02x\n",
pSataChannel->mvSataAdapter->adapterId,
pSataChannel->channelNumber, ATAstatus);
}
return;
}
if (ATAstatus & MV_ATA_ERROR_STATUS)
{
completePIOCommand(pSataChannel, pCommandEntry, MV_TRUE);
return;
}
switch (pCommandEntry->commandInfo.commandParams.NoneUdmaCommand.protocolType)
{
case MV_NON_UDMA_PROTOCOL_NON_DATA:
/* command is successfully completed*/
completePIOCommand(pSataChannel, pCommandEntry, MV_FALSE);
break;
case MV_NON_UDMA_PROTOCOL_PIO_DATA_IN:
if (ATAstatus & MV_ATA_READY_STATUS)
{
if (transferPIOData(pSataChannel,
&pCommandEntry->commandInfo.commandParams.NoneUdmaCommand) == MV_TRUE)
{
if (pCommandEntry->commandInfo.commandParams.NoneUdmaCommand.count == 0)
{
completePIOCommand(pSataChannel, pCommandEntry, MV_FALSE);
}
#ifdef MV_SATA_SUPPORT_READ_WRITE_LONG
/* for Read long only*/
if (pCommandEntry->commandInfo.commandParams.NoneUdmaCommand.count == 4)
{
if (transferPIOData(pSataChannel,
&pCommandEntry->commandInfo.commandParams.NoneUdmaCommand) == MV_TRUE)
{
completePIOCommand(pSataChannel, pCommandEntry, MV_FALSE);
}
else
{
completePIOCommand(pSataChannel, pCommandEntry, MV_TRUE);
}
}
#endif /*MV_SATA_SUPPORT_READ_WRITE_LONG*/
}
else
{
completePIOCommand(pSataChannel, pCommandEntry, MV_TRUE);
}
}
else /* when BUSY and DRQ cleared to zero then the device has*/
{
/* completed the command with error */
completePIOCommand(pSataChannel, pCommandEntry, MV_TRUE);
return;
}
break;
case MV_NON_UDMA_PROTOCOL_PIO_DATA_OUT:
if ((ATAstatus & MV_ATA_READY_STATUS) &&
!(ATAstatus & MV_ATA_DEVICE_FAULT_STATUS))
{
if (pCommandEntry->commandInfo.commandParams.NoneUdmaCommand.count == 0)
{
completePIOCommand(pSataChannel, pCommandEntry, MV_FALSE);
}
else
{
if (transferPIOData(pSataChannel,
&pCommandEntry->commandInfo.commandParams.NoneUdmaCommand) == MV_FALSE)
{
completePIOCommand(pSataChannel, pCommandEntry, MV_TRUE);
}
}
}
else
{
mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%d %d: PIO Interrupt: PIO"
" Data Out command failed status 0x%02x\n",
pSataChannel->mvSataAdapter->adapterId,
pSataChannel->channelNumber, ATAstatus);
completePIOCommand(pSataChannel, pCommandEntry, MV_TRUE);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -