📄 mvstoragedev.c
字号:
enableStorageDevInterrupt(pSataChannel);
return MV_FALSE;
}
enableStorageDevInterrupt(pSataChannel);
return MV_TRUE;
}
/* Wait for the command to complete */
if (waitWhileStorageDevIsBusy(pAdapter, ioBaseAddr, eDmaRegsOffset, 3100, 10000) ==
MV_FALSE)
{
enableStorageDevInterrupt(pSataChannel);
return MV_FALSE;
}
/* Check the status register on DATA request commands */
ATAstatus = MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset +
MV_ATA_DEVICE_STATUS_REG_OFFSET);
if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_I)
{
if (!(ATAstatus & MV_ATA_DATA_REQUEST_STATUS))
{
mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: DRQ bit in ATA STATUS"
" register is not set\n", pAdapter->adapterId, channelIndex);
enableStorageDevInterrupt(pSataChannel);
return MV_FALSE;
}
}
if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_II)
{
if (waitForDRQ(pAdapter, ioBaseAddr, eDmaRegsOffset, 500, 10000)
== MV_FALSE)
{
mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: DRQ bit in ATA STATUS"
" register is not set\n", pAdapter->adapterId, channelIndex);
enableStorageDevInterrupt(pSataChannel);
return MV_FALSE;
}
}
for (i = 0; i < count; i++)
{
/* Every 256 loops (one sector has been transfered) we have to check the
BUSY bit to verify that the Disk is ready for next block transfer */
if ((i & 0xff) == 0)
{
if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_II)
{
/* Perform a dummy read */
MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset +
MV_ATA_DEVICE_STATUS_REG_OFFSET);
mvMicroSecondsDelay (pAdapter, 1);
}
if (waitWhileStorageDevIsBusy(pAdapter,
ioBaseAddr, eDmaRegsOffset,
50000, 100) == MV_FALSE)
{
enableStorageDevInterrupt(pSataChannel);
return MV_FALSE;
}
if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_II)
{
if (waitForDRQ(pAdapter, ioBaseAddr, eDmaRegsOffset, 50000, 100)
== MV_FALSE)
{
enableStorageDevInterrupt(pSataChannel);
return MV_FALSE;
}
}
}
if (protocolType == MV_NON_UDMA_PROTOCOL_PIO_DATA_IN)
{
bufPtr[i] = MV_REG_READ_WORD(ioBaseAddr, eDmaRegsOffset +
MV_ATA_DEVICE_PIO_DATA_REG_OFFSET);
}
else
{
MV_REG_WRITE_WORD(ioBaseAddr, eDmaRegsOffset +
MV_ATA_DEVICE_PIO_DATA_REG_OFFSET, bufPtr[i]);
MV_CPU_WRITE_BUFFER_FLUSH();
}
}
/* Wait for the storage device to be available */
mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d %d: on non-UDMA sequence - checking if"
" device is has finished the command\n",
pAdapter->adapterId, channelIndex);
if (waitWhileStorageDevIsBusy(pAdapter,
ioBaseAddr, eDmaRegsOffset, 50000, 100) ==
MV_FALSE)
{
enableStorageDevInterrupt(pSataChannel);
return MV_FALSE;
}
if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_II)
{
if (waitForDRQToClear(pAdapter, ioBaseAddr, eDmaRegsOffset, 50000, 1)
== MV_FALSE)
{
enableStorageDevInterrupt(pSataChannel);
return MV_FALSE;
}
}
mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d %d: Finish NonUdma Command. Status=0x%02x"
"\n", pAdapter->adapterId, channelIndex,
MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset +
MV_ATA_DEVICE_STATUS_REG_OFFSET));
enableStorageDevInterrupt(pSataChannel);
return MV_TRUE;
}
MV_BOOLEAN _PMAccessReg(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex,
MV_U8 PMPort, MV_U8 PMReg, MV_U32 *pValue,
MV_STORAGE_DEVICE_REGISTERS *registerStruct,
MV_BOOLEAN isRead)
{
MV_BOOLEAN result;
if (isRead == MV_TRUE)
{
result = executeNonUDMACommand(pAdapter, channelIndex,
MV_SATA_PM_CONTROL_PORT,
MV_NON_UDMA_PROTOCOL_NON_DATA,
MV_FALSE/*isEXT*/,
NULL/*bufPtr*/,
0/*count*/,
PMReg /*features*/, 0/*sectorCount*/,
0 /*lbaLow*/, 0 /*lbaMid*/, 0 /*lbaHigh*/,
PMPort/*device*/,
MV_ATA_COMMAND_PM_READ_REG/*command*/);
if (result == MV_TRUE)
{
MV_BUS_ADDR_T ioBaseAddr = pAdapter->adapterIoBaseAddress;
MV_U32 eDmaRegsOffset = pAdapter->sataChannel[channelIndex]->eDmaRegsOffset;
*pValue = MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset +
MV_ATA_DEVICE_SECTOR_COUNT_REG_OFFSET);
*pValue |= MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset +
MV_ATA_DEVICE_LBA_LOW_REG_OFFSET) << 8;
*pValue |= MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset +
MV_ATA_DEVICE_LBA_MID_REG_OFFSET) << 16;
*pValue |= MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset +
MV_ATA_DEVICE_LBA_HIGH_REG_OFFSET) << 24;
}
}
else
{
result = executeNonUDMACommand(pAdapter, channelIndex,
MV_SATA_PM_CONTROL_PORT,
MV_NON_UDMA_PROTOCOL_NON_DATA,
MV_FALSE/*isEXT*/,
NULL/*bufPtr*/,
0/*count*/,
PMReg /*features*/,
(MV_U16)((*pValue) & 0xff)/*sectorCount*/,
(MV_U16)(((*pValue) & 0xff00) >> 8) /*lbaLow*/,
(MV_U16)(((*pValue) & 0xff0000) >> 16) /*lbaMid*/,
(MV_U16)(((*pValue) & 0xff000000) >> 24) /*lbaHigh*/,
PMPort/*device*/,
MV_ATA_COMMAND_PM_WRITE_REG/*command*/);
}
if (registerStruct)
{
dumpAtaDeviceRegisters(pAdapter, channelIndex, MV_FALSE,
registerStruct);
}
mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG|MV_DEBUG_PM, " %d %d: %s PM Reg %s: PM Port %x"
", PM Reg %d, value %x\n", pAdapter->adapterId, channelIndex,
(isRead == MV_TRUE) ? "Read" : "Write",
(result == MV_TRUE) ? "Succeeded" : "Failed",
PMPort, PMReg, *pValue);
return result;
}
MV_BOOLEAN waitForDRQToClear(MV_SATA_ADAPTER* pAdapter,
MV_BUS_ADDR_T ioBaseAddr,
MV_U32 eDmaRegsOffset, MV_U32 loops,
MV_U32 delay)
{
MV_U8 ATAstatus = 0;
MV_U32 i;
for (i = 0;i < loops; i++)
{
ATAstatus = MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset +
MV_ATA_DEVICE_STATUS_REG_OFFSET);
if ((ATAstatus & MV_ATA_BUSY_STATUS) == 0)
{
if (!(ATAstatus & MV_ATA_DATA_REQUEST_STATUS))
{
mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, "waitWhileStorageDevIsBusy: %d loops *"
"%d usecs\n", i, delay);
return MV_TRUE;
}
}
mvMicroSecondsDelay(pAdapter, delay);
}
mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "waitWhileStorageDevIsBusy<FAILED>: Time out - Device ERROR"
" Status: 0x%02x. loops %d, delay %d\n", ATAstatus, loops, delay);
return MV_FALSE;
}
void dumpAtaDeviceRegisters(MV_SATA_ADAPTER *pAdapter,
MV_U8 channelIndex, MV_BOOLEAN isEXT,
MV_STORAGE_DEVICE_REGISTERS *pRegisters)
{
MV_BUS_ADDR_T ioBaseAddr = pAdapter->adapterIoBaseAddress;
MV_U32 eDmaRegsOffset = pAdapter->sataChannel[channelIndex]->eDmaRegsOffset;
MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset +
MV_ATA_DEVICE_CONTROL_REG_OFFSET, 0);
pRegisters->errorRegister =
MV_REG_READ_BYTE(ioBaseAddr,
eDmaRegsOffset + MV_ATA_DEVICE_ERROR_REG_OFFSET);
pRegisters->sectorCountRegister =
MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset +
MV_ATA_DEVICE_SECTOR_COUNT_REG_OFFSET) & 0x00ff;
pRegisters->lbaLowRegister =
MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset +
MV_ATA_DEVICE_LBA_LOW_REG_OFFSET) & 0x00ff;
pRegisters->lbaMidRegister =
MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset +
MV_ATA_DEVICE_LBA_MID_REG_OFFSET) & 0x00ff;
pRegisters->lbaHighRegister =
MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset +
MV_ATA_DEVICE_LBA_HIGH_REG_OFFSET) & 0x00ff;
if (isEXT == MV_TRUE)
{
/*set the HOB bit of DEVICE CONTROL REGISTER */
MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset +
MV_ATA_DEVICE_CONTROL_REG_OFFSET, MV_BIT7);
pRegisters->sectorCountRegister |= (MV_REG_READ_BYTE(ioBaseAddr,
eDmaRegsOffset +
MV_ATA_DEVICE_SECTOR_COUNT_REG_OFFSET) << 8) & 0xff00;
pRegisters->lbaLowRegister |= (MV_REG_READ_BYTE(ioBaseAddr,
eDmaRegsOffset + MV_ATA_DEVICE_LBA_LOW_REG_OFFSET) << 8)
& 0xff00;
pRegisters->lbaMidRegister |= (MV_REG_READ_BYTE(ioBaseAddr,
eDmaRegsOffset + MV_ATA_DEVICE_LBA_MID_REG_OFFSET) << 8)
& 0xff00;
pRegisters->lbaHighRegister |= (MV_REG_READ_BYTE(ioBaseAddr,
eDmaRegsOffset + MV_ATA_DEVICE_LBA_HIGH_REG_OFFSET) << 8)
& 0xff00;
MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset +
MV_ATA_DEVICE_CONTROL_REG_OFFSET, 0);
}
pRegisters->deviceRegister = MV_REG_READ_BYTE(ioBaseAddr,
eDmaRegsOffset + MV_ATA_DEVICE_HEAD_REG_OFFSET);
pRegisters->statusRegister = MV_REG_READ_BYTE(ioBaseAddr,
eDmaRegsOffset + MV_ATA_DEVICE_STATUS_REG_OFFSET);
}
MV_BOOLEAN _doSoftReset(MV_SATA_CHANNEL *pSataChannel)
{
MV_BUS_ADDR_T ioBaseAddr = pSataChannel->mvSataAdapter->adapterIoBaseAddress;
MV_U32 i;
MV_U8 ATAstatus;
MV_U32 eDmaRegsOffset = pSataChannel->eDmaRegsOffset;
mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_NON_UDMA_COMMAND | MV_DEBUG, "Issue SRST COMMAND\n");
/* Write to the Device Control register, bits 1,2: */
/* - bit 1 (nIEN): is the enable bit for the device assertion of INTRQ */
/* to the host. When the nIEN bit is set to one, or the device is not */
/* selected, the device shall release the INTRQ signal. */
/* - bit 2 (SRST): is the host software reset bit. */
MV_REG_WRITE_BYTE(ioBaseAddr, pSataChannel->eDmaRegsOffset +
MV_ATA_DEVICE_CONTROL_REG_OFFSET, MV_BIT2|MV_BIT1);
MV_REG_READ_BYTE(ioBaseAddr, pSataChannel->eDmaRegsOffset +
MV_ATA_DEVICE_CONTROL_REG_OFFSET);
mvMicroSecondsDelay(pSataChannel->mvSataAdapter, 10);
/* enableStorageDevInterrupt will clear the SRST bit*/
enableStorageDevInterrupt(pSataChannel);
mvMicroSecondsDelay(pSataChannel->mvSataAdapter, 500);
mvMicroSecondsDelay(pSataChannel->mvSataAdapter, 500);
mvMicroSecondsDelay(pSataChannel->mvSataAdapter, 500);
mvMicroSecondsDelay(pSataChannel->mvSataAdapter, 500);
for (i = 0;i < 31000; i++)
{
ATAstatus = MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset +
MV_ATA_DEVICE_STATUS_REG_OFFSET);
if ((ATAstatus & MV_ATA_BUSY_STATUS) == 0)
{
return MV_TRUE;
}
mvMicroSecondsDelay(pSataChannel->mvSataAdapter, 1000);
}
mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: Software reset failed "
"Status=0x%02x\n", pSataChannel->mvSataAdapter->adapterId,
pSataChannel->channelNumber, ATAstatus);
return MV_FALSE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -