📄 mvstoragedev.c
字号:
/*******************************************************************************
*
* Copyright 2003,MARVELL SEMICONDUCTOR ISRAEL, LTD.
* THIS CODE CONTAINS CONFIDENTIAL INFORMATION OF MARVELL.
* 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.
*
* MARVELL COMPRISES MARVELL TECHNOLOGY GROUP LTD. (MTGL) AND ITS SUBSIDIARIES,
* MARVELL INTERNATIONAL LTD. (MIL), MARVELL TECHNOLOGY, INC. (MTI), MARVELL
* SEMICONDUCTOR, INC. (MSI), MARVELL ASIA PTE LTD. (MAPL), MARVELL JAPAN K.K.
* (MJKK), MARVELL SEMICONDUCTOR ISRAEL. (MSIL), MARVELL TAIWAN, LTD. AND
* SYSKONNECT GMBH.
********************************************************************************
* mvStorageDev.c - C File for implementation of the core driver.
*
* DESCRIPTION:
* None.
*
* DEPENDENCIES:
* mvOs.h
* mvSata.h.
* mvStorageDev.h
* mvRegs.h
*
* FILE REVISION NUMBER:
* $Revision: 1.12 $
*******************************************************************************/
#include "mvOs.h"
#include "mvSata.h"
#include "mvStorageDev.h"
#include "mvRegs.h"
/* Defines */
/* functions for internal driver use */
MV_BOOLEAN waitWhileStorageDevIsBusy(MV_SATA_ADAPTER* pAdapter,
MV_BUS_ADDR_T ioBaseAddr,
MV_U32 eDmaRegsOffset, MV_U32 loops,
MV_U32 delay);
MV_BOOLEAN waitForDRQToClear(MV_SATA_ADAPTER* pAdapter,
MV_BUS_ADDR_T ioBaseAddr,
MV_U32 eDmaRegsOffset, MV_U32 loops,
MV_U32 delay);
void enableStorageDevInterrupt (MV_SATA_CHANNEL *pSataChannel);
void disableStorageDevInterrupt(MV_SATA_CHANNEL *pSataChannel);
static MV_BOOLEAN isStorageDevReadyForPIO(MV_SATA_CHANNEL *pSataChannel);
void dumpAtaDeviceRegisters(MV_SATA_ADAPTER *pAdapter,
MV_U8 channelIndex, MV_BOOLEAN isEXT,
MV_STORAGE_DEVICE_REGISTERS *pRegisters);
MV_BOOLEAN _doSoftReset(MV_SATA_CHANNEL *pSataChannel);
extern void _setActivePMPort(MV_SATA_CHANNEL *pSataChannel, MV_U8 PMPort);
extern void disableSaDevInterrutps(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex);
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 executeNonUDMACommand(MV_SATA_ADAPTER *pAdapter,
MV_U8 channelIndex,
MV_U8 PMPort,
MV_NON_UDMA_PROTOCOL protocolType,
MV_BOOLEAN isEXT,
MV_U16_PTR bufPtr, MV_U32 count,
MV_U16 features,
MV_U16 sectorCount,
MV_U16 lbaLow, MV_U16 lbaMid,
MV_U16 lbaHigh, MV_U8 device,
MV_U8 command);
/*******************************************************************************
* waitWhileStorageDevIsBusy - Wait for the storage device to be released from
* busy state.
*
* DESCRIPTION:
* The busy bit is set to one to indicate that the storage device is busy. The
* busy bit shall be set to one by the device only when one of the following
* events occurs:
*
* 1) after either the negation of RESET- or the setting of the SRST bit to one
* in the Device Control register.
* 2) after writing the Command register if the DRQ bit is not set to one.
* 3) between blocks of a data transfer during PIO data-in commands before the
* DRQ bit is cleared to zero.
* 4) after the transfer of a data block during PIO data-out commands before
* the DRQ bit is cleared to zero.
* 5) during the data transfer of DMA commands either the BSY bit, the DRQ bit,
* or both shall be set to one.
* 6) after the command packet is received during the execution of a PACKET
* command.
*
* INPUT:
* ioBaseAddr - The PCI I/O window base address of the adapter.
* eDmaRegsOffset - The EDMA register's offset of the relevant SATA channel.
* loops - max number of times to pool the status register.
* delay - number of u seconds to wait each loop.
*
* RETURN:
* MV_TRUE if the device is released from busy state, MV_FALSE otherwise.
* COMMENTS:
* None.
*
*******************************************************************************/
MV_BOOLEAN waitWhileStorageDevIsBusy(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_ERROR_STATUS) == 0)
{
mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, "waitWhileStorageDevIsBusy: %d loops *"
"%d usecs\n", i, delay);
return MV_TRUE;
}
else
{
mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "waitWhileStorageDevIsBusy<FAILED>: Device ERROR"
" Status: 0x%02x\n", ATAstatus);
return MV_FALSE;
}
}
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;
}
MV_BOOLEAN waitForDRQ(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;
}
/*******************************************************************************
* enableStorageDevInterrupt - Enable the storage device to be able to issue
* interrupt.
*
* DESCRIPTION:
* Enable the connected storage device to the given channel to assert INTRQ by
* clearing nIEN bit in the Device Control register.
*
* INPUT:
* pSataChannel - Pointer to the Sata channel data structure.
*
* RETURN:
* None.
*
* COMMENTS:
* this function also clears the SRST bit in the Device Control register.
*
*******************************************************************************/
void enableStorageDevInterrupt(MV_SATA_CHANNEL *pSataChannel)
{
MV_REG_WRITE_BYTE(pSataChannel->mvSataAdapter->adapterIoBaseAddress,
pSataChannel->eDmaRegsOffset +
MV_ATA_DEVICE_CONTROL_REG_OFFSET,0);
MV_REG_READ_BYTE(pSataChannel->mvSataAdapter->adapterIoBaseAddress,
pSataChannel->eDmaRegsOffset +
MV_ATA_DEVICE_CONTROL_REG_OFFSET);
}
/*******************************************************************************
* disableStorageDevInterrupt - Disable the storage device to be able to issue
* interrupt.
*
* DESCRIPTION:
* This function disable the connected storage device to the given channel to
* assert INTRQ by setting nIEN bit in the Device Control register.
*
* INPUT:
* pSataChannel - Pointer to the Sata channel data structure.
*
* RETURN:
* None.
*
* COMMENTS:
* this function also clears the SRST bit
*
*******************************************************************************/
void disableStorageDevInterrupt(MV_SATA_CHANNEL *pSataChannel)
{
MV_REG_WRITE_BYTE(pSataChannel->mvSataAdapter->adapterIoBaseAddress,
pSataChannel->eDmaRegsOffset +
MV_ATA_DEVICE_CONTROL_REG_OFFSET, MV_BIT1);
MV_REG_READ_BYTE(pSataChannel->mvSataAdapter->adapterIoBaseAddress,
pSataChannel->eDmaRegsOffset +
MV_ATA_DEVICE_STATUS_REG_OFFSET);
}
/*******************************************************************************
* isStorageDevReadyForPIO - Check that the storage device connected to the given
* channel and the channel itself are ready to perform
* PIO commands.
*
* DESCRIPTION:
* Check if the device connected to the given channel and the channel itself
* are ready for PIO commands.
*
* INPUT:
* pSataChannel - Pointer to the SATA channel data structure.
*
* RETURN:
* MV_TRUE if the channel and the connected device ready to do PIO,
* MV_FALSE otherwise.
*
* COMMENTS:
* If the adapter's eEnEDMA bit in the EDMA Command Register is set, PIO
* commands cannot be issued. The eEnEDMA bit cannot be reset by the CPU.
* Only the EDMA resets it, when bit eDsEDMA is set or when an error
* condition occurs.
*
*******************************************************************************/
static MV_BOOLEAN isStorageDevReadyForPIO(MV_SATA_CHANNEL *pSataChannel)
{
MV_BUS_ADDR_T ioBaseAddr =pSataChannel->mvSataAdapter->adapterIoBaseAddress;
MV_U32 eDmaRegsOffset = pSataChannel->eDmaRegsOffset;
MV_U8 ATAcontrolRegValue;
/* If the adapter's eEnEDMA bit in the EDMA Command Register is set */
/* PIO commands cannot be issued. */
if (pSataChannel->queueCommandsEnabled == MV_TRUE)
{
mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: PIO command failed:"
"EDMA is active\n", pSataChannel->mvSataAdapter->adapterId,
pSataChannel->channelNumber);
return MV_FALSE;
}
/* Check if BUSY bit is '0' */
/* Reading the Control register actually gives us the Alternate Status */
/* register content (ATA protocol). If the busy bit is set in the */
/* Alternate Status register, we wait for 50 mili-sec and try again, if */
/* the busy bit is still set, we return false indicating that the */
/* device is not ready for PIO commands. */
ATAcontrolRegValue = MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset +
MV_ATA_DEVICE_CONTROL_REG_OFFSET);
if ((ATAcontrolRegValue & MV_ATA_BUSY_STATUS)!= 0)
{
mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: control regiser is "
"0x%02x\n",pSataChannel->mvSataAdapter->adapterId,
pSataChannel->channelNumber,ATAcontrolRegValue);
return MV_FALSE;
}
if ((ATAcontrolRegValue & MV_ATA_READY_STATUS) !=
MV_ATA_READY_STATUS)
{
mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: storage drive is not"
" ready, ATA STATUS=0x%02x\n",
pSataChannel->mvSataAdapter->adapterId,
pSataChannel->channelNumber, ATAcontrolRegValue);
return MV_FALSE;
}
/* The device is ready for PIO commands */
return MV_TRUE;
}
MV_BOOLEAN mvStorageDevATAIdleImmediate(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex)
{
MV_SATA_CHANNEL *pSataChannel;
MV_BUS_ADDR_T ioBaseAddr;
MV_U32 eDmaRegsOffset;
if (pAdapter == NULL)
{
mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " : mvStorageDevATAIdentif"
"yDevice failed, Bad adapter data structure pointer\n");
return MV_FALSE;
}
pSataChannel = pAdapter->sataChannel[channelIndex];
if (pSataChannel == NULL)
{ /* If the pointer do not exists, retrun false */
mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: channel data "
"structure is not allocated\n", pAdapter->adapterId,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -