blob: 5abaa9cdf6ed8c7e6bb78eb2af3d59002e7b0725 [file] [log] [blame]
/*******************************************************************************
Copyright (C) Marvell International Ltd. and its affiliates
This software file (the "File") is owned and distributed by Marvell
International Ltd. and/or its affiliates ("Marvell") under the following
alternative licensing terms. Once you have made an election to distribute the
File under one of the following license alternatives, please (i) delete this
introductory statement regarding license alternatives, (ii) delete the two
license alternatives that you have not elected to use and (iii) preserve the
Marvell copyright notice above.
********************************************************************************
Marvell GPL License Option
If you received this File from Marvell, you may opt to use, redistribute and/or
modify this File in accordance with the terms and conditions of the General
Public License Version 2, June 1991 (the "GPL License"), a copy of which is
available along with the File in the license.txt file or by writing to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
DISCLAIMED. The GPL License provides additional details about this warranty
disclaimer.
*******************************************************************************/
/*******************************************************************************
* mvScsiAtaLayer.c
*
* DESCRIPTION:
* C implementation for SCSI to ATA translation layer.
*
* DEPENDENCIES:
* mvIALCommonUtils.h
* mvSata.h
* mvStorageDev.h
* mvOs.h
*
*******************************************************************************/
#ifndef __INCmvScsiAtaLayer
#define __INCmvScsiAtaLayer
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* includes */
#include "mvOs.h"
#include "mvSata.h"
#include "mvStorageDev.h"
#include "mvIALCommonUtils.h"
/* Defines */
#define MV_SAL_LOG_ID 1
#ifndef IN
#define IN
#endif
#ifndef OUT
#define OUT
#endif
#ifndef INOUT
#define INOUT
#endif
/* Scsi opcodes*/
/* 6 - bytes commands*/
#define SCSI_OPCODE_TEST_UNIT_READY 0x00
#define SCSI_OPCODE_REPORT_LUNS 0xA0
#define SCSI_OPCODE_REQUEST_SENSE6 0x03
#define SCSI_OPCODE_REASSIGN_BLOCKS 0x07
#define SCSI_OPCODE_READ6 0x08
#define SCSI_OPCODE_WRITE6 0x0A
#define SCSI_OPCODE_INQUIRY 0x12
#define SCSI_OPCODE_VERIFY6 0x13
#define SCSI_OPCODE_MODE_SELECT6 0x15
#define SCSI_OPCODE_MODE_SENSE6 0x1A
#define SCSI_OPCODE_START_STOP 0x1B
/* 10 - bytes commands*/
#define SCSI_OPCODE_READ_CAPACITY10 0x25
#define SCSI_OPCODE_READ10 0x28
#define SCSI_OPCODE_WRITE10 0x2A
#define SCSI_OPCODE_VERIFY10 0x2F
#define SCSI_OPCODE_SYNCHRONIZE_CACHE10 0x35
#define SCSI_OPCODE_SEEK10 0x2B
#define SCSI_OPCODE_WRITE_LONG10 0x3F
#define SCSI_OPCODE_READ_LONG10 0x3E
/* 12 - bytes commands */
/* 16 - bytes commands */
#define SCSI_OPCODE_READ_CAPACITY16 0x9E
#define SCSI_OPCODE_READ16 0x88
#define SCSI_OPCODE_WRITE16 0x8A
#define SCSI_OPCODE_VERIFY16 0x8F
#define SCSI_OPCODE_SYNCHRONIZE_CACHE16 0x91
#define SCSI_OPCODE_ATA16 0x85
#define SCSI_OPCODE_ATA12 0xA1
/* SCSI bus status codes */
#define MV_SCSI_STATUS_GOOD 0x00
#define MV_SCSI_STATUS_CHECK_CONDITION 0x02
#define MV_SCSI_STATUS_CONDITION_MET 0x04
#define MV_SCSI_STATUS_BUSY 0x08
#define MV_SCSI_STATUS_INTERMEDIATE 0x10
#define MV_SCSI_STATUS_INTERMEDIATE_COND_MET 0x14
#define MV_SCSI_STATUS_RESERVATION_CONFLICT 0x18
#define MV_SCSI_STATUS_COMMAND_TERMINATED 0x22
#define MV_SCSI_STATUS_QUEUE_FULL 0x28
/* Typedefs */
#if 0
/* Scsi Sense Data Format */
/* Max length - 18 bytes, the additional sense length will not exceed 10 bytes*/
typedef struct _mvScsiSenseData
{
#ifdef MV_BIG_ENDIAN_BITFIELD
MV_U8 Valid:1;
MV_U8 ResponseCode:7;
#else
MV_U8 ResponseCode:7;
MV_U8 Valid:1;
#endif
MV_U8 Reserved1;
#ifdef MV_BIG_ENDIAN_BITFIELD
MV_U8 FileMark:1;
MV_U8 EOM:1; /* End Of Media */
MV_U8 ILI:1; /* Incorrect Length Indicator*/
MV_U8 Reserved2:1;
MV_U8 SenseKey:4;
#else
MV_U8 SenseKey:4;
MV_U8 Reserved2:1;
MV_U8 ILI:1; /* Incorrect Length Indicator*/
MV_U8 EOM:1; /* End Of Media */
MV_U8 FileMark:1;
#endif
MV_U8 Information[4];
MV_U8 AdditionalSenseLength;
MV_U8 CommandSpecificInformation[4];
MV_U8 AdditionalSenseCode;
MV_U8 AdditionalSenseCodeQualifier;
MV_U8 FieldReplaceableUnitCode;
MV_U8 SenseKeySpecific[3];
} MV_SCSI_SENSE_DATA;
#else
/* Scsi Sense Data Descriptor Format + information descriptor */
/* Max length - 18 bytes, the additional sense length will not exceed 10 bytes*/
typedef struct _mvScsiInfoSenseDesc
{
MV_U8 type;
MV_U8 AdditionalLength;
MV_U8 valid;
MV_U8 reserved;
MV_U8 information[11-4+1];
}MV_SCSI_INFO_SENSE_DESC;
typedef struct _mvScsiSenseData
{
MV_U8 ResponseCode;
#ifdef MV_BIG_ENDIAN_BITFIELD
MV_U8 Reserved:4;
MV_U8 SenseKey:4;
#else
MV_U8 SenseKey:4;
MV_U8 Reserved:4;
#endif
MV_U8 AdditionalSenseCode;
MV_U8 AdditionalSenseCodeQualifier;
MV_U8 Reserved2[3];
MV_U8 AdditionalSenseLength;
MV_SCSI_INFO_SENSE_DESC InformationDesc;
} MV_SCSI_SENSE_DATA;
#endif
/* Sense codes */
#define SCSI_SENSE_NO_SENSE 0x00
#define SCSI_SENSE_RECOVERED_ERROR 0x01
#define SCSI_SENSE_NOT_READY 0x02
#define SCSI_SENSE_MEDIUM_ERROR 0x03
#define SCSI_SENSE_HARDWARE_ERROR 0x04
#define SCSI_SENSE_ILLEGAL_REQUEST 0x05
#define SCSI_SENSE_UNIT_ATTENTION 0x06
#define SCSI_SENSE_DATA_PROTECT 0x07
#define SCSI_SENSE_BLANK_CHECK 0x08
#define SCSI_SENSE_UNIQUE 0x09
#define SCSI_SENSE_COPY_ABORTED 0x0A
#define SCSI_SENSE_ABORTED_COMMAND 0x0B
#define SCSI_SENSE_EQUAL 0x0C
#define SCSI_SENSE_VOL_OVERFLOW 0x0D
#define SCSI_SENSE_MISCOMPARE 0x0E
#define SCSI_SENSE_RESERVED 0x0F
/* Additional Sense codes */
#define SCSI_ADSENSE_NO_SENSE 0x00
#define SCSI_ADSENSE_ILLEGAL_COMMAND 0x20
#define SCSI_ADSENSE_ILLEGAL_BLOCK 0x21
#define SCSI_ADSENSE_INVALID_CDB 0x24
#define SCSI_ADSENSE_INVALID_LUN 0x25
#define SCSI_ADSENSE_INVALID_FIELD_IN_PARAMETER_LIST 0x26
#define SCSI_ADSENSE_BUS_RESET 0x29
#define SCSI_ADSENSE_PARAMETERS_CHANGED 0x2A
#define SCSI_ADSENSE_NO_MEDIA_IN_DEVICE 0x3a
#define MV_SCSI_RESPONSE_CODE 0x72
#define MV_SCSI_DIRECT_ACCESS_DEVICE 0x00
#define MV_MAX_MODE_SENSE_RESULT_LENGTH 50
/* Typedefs */
typedef enum _mvScsiCompletionType
{
MV_SCSI_COMPLETION_INVALID_STATUS,
MV_SCSI_COMPLETION_SUCCESS,
MV_SCSI_COMPLETION_BAD_SCB,
MV_SCSI_COMPLETION_BAD_SCSI_COMMAND,
MV_SCSI_COMPLETION_ATA_FAILED,
MV_SCSI_COMPLETION_QUEUE_FULL,
MV_SCSI_COMPLETION_NOT_READY,
MV_SCSI_COMPLETION_ABORTED,
MV_SCSI_COMPLETION_OVERRUN,
MV_SCSI_COMPLETION_UNDERRUN,
MV_SCSI_COMPLETION_PARITY_ERROR,
MV_SCSI_COMPLETION_DISCONNECT,
MV_SCSI_COMPLETION_NO_DEVICE,
MV_SCSI_COMPLETION_INVALID_BUS,
MV_SCSI_COMPLETION_BUS_RESET,
MV_SCSI_COMPLETION_BUSY,
MV_SCSI_COMPLETION_UA_RESET,
MV_SCSI_COMPLETION_UA_PARAMS_CHANGED
}MV_SCSI_COMPLETION_TYPE;
typedef enum _mvScsiCommandStatus
{
MV_SCSI_COMMAND_STATUS_COMPLETED,
MV_SCSI_COMMAND_STATUS_QUEUED,
MV_SCSI_COMMAND_STATUS_FAILED,
MV_SCSI_COMMAND_STATUS_QUEUED_BY_IAL
}MV_SCSI_COMMAND_STATUS_TYPE;
typedef enum _mvScsiCommandDataDirection
{
MV_SCSI_COMMAND_DATA_DIRECTION_NON,
MV_SCSI_COMMAND_DATA_DIRECTION_IN,
MV_SCSI_COMMAND_DATA_DIRECTION_OUT
} MV_SCSI_COMMAND_DATA_DIRECTION;
struct _mvSataScsiCmdBlock;
typedef MV_BOOLEAN (* mvScsiCommandCompletionCallBack)(struct mvSataAdapter *,
struct _mvSataScsiCmdBlock*);
struct mvSalAdapterExtension;
struct mvIalCommonAdapterExtension;
typedef struct _mvSataScsiCmdBlock
{
/* the Scsi command data block buffer*/
IN MV_U8* ScsiCdb;
/* the length in bytes of the CDB (6,10,12,16)*/
IN MV_U32 ScsiCdbLength;
/* the scsi bus*/
IN MV_U8 bus;
/* the target device id*/
IN MV_U8 target;
/* scsi lun number of the device*/
IN MV_U8 lun;
/* True when the data located in the buffer pointed by pDataBuffer */
/* (virtual address), false when the command is READ/WRITE, in this */
/* case the data located in a PRD table*/
/*IN MV_BOOLEAN useSingleBuffer;*/
/* pointer to the command data buffer*/
IN MV_U8 *pDataBuffer;
/* length in bytes of the command data buffer*/
IN MV_U32 dataBufferLength;
/* number of entries in the PRD table*/
/*IN MV_U32 PRDTableEntries; */
/* low 32 bits of the PRD table physical address*/
IN MV_U32 PRDTableLowPhyAddress;
/* high 32 bits of the PRD table physical address*/
IN MV_U32 PRDTableHighPhyAddress;
#ifdef MV_SATA_SUPPORT_EDMA_SINGLE_DATA_REGION
MV_BOOLEAN singleDataRegion;
MV_U16 byteCount;
#endif
/* the Scsi status will be written to this field*/
OUT MV_U8 ScsiStatus;
/* pointer to the Scsi sense buffer*/
IN MV_U8* pSenseBuffer;
/* length in bytes of the Scsi sense buffer*/
IN MV_U32 senseBufferLength;
/* length in bytes of the generated sense data*/
OUT MV_U32 senseDataLength;
/* length in bytes of the data transferred to the data buffer/s*/
OUT MV_U32 dataTransfered;
/* the translation layer status of the completed Scsi command */
OUT MV_SCSI_COMPLETION_TYPE ScsiCommandCompletion;
/* call back function called by the translation layer when the Scsi */
/* completed */
IN mvScsiCommandCompletionCallBack completionCallBack;
IN struct mvSalAdapterExtension * pSalAdapterExtension;
IN struct mvIALCommonAdapterExtension* pIalAdapterExtension;
IN MV_SCSI_COMMAND_DATA_DIRECTION dataDirection;
#ifdef MV_SATA_STORE_COMMANDS_INFO_ON_IAL_STACK
MV_QUEUE_COMMAND_INFO *pCommandInfo;
#endif
/* field for IAL usage only*/
MV_VOID_PTR IALData;
/* fields for internal usage for the translation layer*/
MV_UDMA_TYPE udmaType;
MV_QUEUED_COMMAND_TYPE commandType;
/* used for sense buffer */
MV_U32 LowLbaAddress;
/* Used for non-UDMA and for sense buffer */
MV_BOOLEAN isExtended;
MV_U16 splitCount;
MV_U16 sequenceNumber;
/* used to create list for comands that need post interrupt service */
struct _mvSataScsiCmdBlock *pNext;
#ifdef MV_LOGGER
MV_STORAGE_DEVICE_REGISTERS ATAregStruct;
#endif
}MV_SATA_SCSI_CMD_BLOCK;
typedef struct
{
MV_U32 totalIOs;
MV_U32 totalSectorsTransferred;
}MV_SATA_SCSI_CHANNEL_STATS;
typedef struct
{
MV_BOOLEAN driveReady;
ATA_IDENTIFY_INFO identifyInfo;
MV_U16_PTR identifyBuffer;
MV_SATA_SCSI_CHANNEL_STATS stats;
MV_BOOLEAN UAConditionPending;
MV_U8 UAEvents;
}MV_SATA_SCSI_DRIVE_DATA;
typedef struct mvSalAdapterExtension
{
MV_SATA_ADAPTER *pSataAdapter;
MV_SATA_SCSI_CMD_BLOCK *pHead;
MV_U8 UAMask;/*which UA condictions to report*/
MV_U32 totalAccumulatedOutstanding[MV_SATA_CHANNELS_NUM];
MV_SATA_SCSI_DRIVE_DATA ataDriveData[MV_SATA_CHANNELS_NUM][MV_SATA_PM_MAX_PORTS];
MV_U16 identifyBuffer[MV_SATA_CHANNELS_NUM][MV_ATA_IDENTIFY_DEV_DATA_LENGTH];
}MV_SAL_ADAPTER_EXTENSION;
MV_VOID mvSataScsiInitAdapterExt(MV_SAL_ADAPTER_EXTENSION *pAdapterExt,
MV_SATA_ADAPTER* pSataAdapter);
MV_VOID mvSataScsiPostIntService(MV_SAL_ADAPTER_EXTENSION *pAdapterExt);
MV_SCSI_COMMAND_STATUS_TYPE mvSataExecuteScsiCommand(MV_SATA_SCSI_CMD_BLOCK *pMvSataScsiCmdBlock);
MV_VOID mvSataScsiSetDriveReady(MV_SAL_ADAPTER_EXTENSION *pAdapterExt,
MV_U8 channelIndex, MV_U8 PMPort,
MV_BOOLEAN isReady);
MV_VOID mvSataScsiNotifyUA(MV_SAL_ADAPTER_EXTENSION *pAdapterExt,
MV_U8 channelIndex, MV_U8 PMPort);
/* Locals */
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __IsNCmvScsiAtaLayer */