blob: a512955f906dbe10af055a25e8af58a1dfd07398 [file] [log] [blame]
/* Copyright (c) 2013-2015 The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _UCS_H
#define _UCS_H
#include <upiu.h>
#define SCSI_MAX_DATA_TRANS_BLK_LEN 0xFFFF
#define UFS_DEFAULT_SECTORE_SIZE 4096
#define SCSI_STATUS_GOOD 0x00
#define SCSI_STATUS_CHK_COND 0x02
#define SCSI_STATUS_BUSY 0x08
#define SCSI_STATUS_TASK_SET_FULL 0x08
#define SCSI_SENSE_BUF_LEN 0x20
#define SCSI_INQUIRY_LEN 36
#define SCSI_CDB_PARAM_LEN 16
#define SCSI_SEC_PROT 0xEC
#define SCSI_SEC_UFS_PROT_ID 0x0001
/* FLAGS for indication of read or write */
enum scsi_upiu_flags
{
UPIU_FLAGS_READ = 0x40,
UPIU_FLAGS_WRITE = 0x20,
UPIU_FLAGS_ATTR_SIMPLE = 0x00,
UPIU_FLAGS_ATTR_ORDERED = 0x01,
UPIU_FLAGS_ATTR_HOQ = 0x02,
};
#define SCSI_READ_WRITE_10_CDB1(rd_protect, dpo, fua, fua_nv) ((rd_protect) << 5 | (dpo) << 4 | (fua) << 3 | (fua_nv) << 1)
/* SCSI commands */
enum utp_scsi_cmd_type
{
SCSI_CMD_TEST_UNIT_RDY = 0x00,
SCSI_CMD_SENSE_REQ = 0x03,
SCSI_CMD_INQUIRY = 0x12,
SCSI_CMD_READ10 = 0x28,
SCSI_CMD_READ_CAP10 = 0x25, // Read Capacity
SCSI_CMD_SYNC_CACHE10 = 0x35,
SCSI_CMD_UNMAP = 0x42,
SCSI_CMD_WRITE10 = 0x2A,
SCSI_CMD_SECPROT_IN = 0xA2, // Security Protocal in
SCSI_CMD_SECPROT_OUT = 0xB5, // Security Protocal out
SCSI_CMD_REPORT_LUNS = 0xA0,
};
struct scsi_req_build_type
{
addr_t cdb;
uint8_t lun;
addr_t data_buffer_addr;
uint32_t data_len;
enum scsi_upiu_flags flags;
enum upiu_dd_type dd;
};
struct scsi_rdwr_req
{
uint8_t lun;
uint32_t start_lba;
uint32_t num_blocks;
uint32_t data_buffer_base;
};
struct scsi_sec_protocol_cdb
{
uint8_t opcode;
uint8_t cdb1;
uint16_t sec_protocol_specific;
uint8_t resv1;
uint8_t resv2;
uint32_t alloc_tlen;
uint8_t resv3;
uint8_t control;
}__PACKED;
struct scsi_rdwr_cdb
{
uint8_t opcode;
uint8_t cdb1;
uint32_t lba;
uint8_t grp_num;
uint16_t trans_len;
uint8_t control;
uint8_t resv[6];
}__PACKED;
struct scsi_unmap_req
{
uint8_t lun;
uint64_t start_lba;
uint32_t num_blocks;
}__PACKED;
struct unmap_blk_desc
{
uint64_t lba;
uint32_t num_blks;
uint32_t reserved;
}__PACKED;
struct unmap_param_list
{
uint16_t data_len;
uint16_t blk_desc_data_len;
uint32_t reserved;
struct unmap_blk_desc blk_desc;
}__PACKED;
struct scsi_sense_cdb
{
uint8_t opcode;
uint8_t desc;
uint16_t resv_0;
uint8_t alloc_len;
uint8_t control;
uint8_t resv_1[10];
}__PACKED;
struct scsi_failure_sense_data
{
uint8_t valid_resp_code;
uint8_t obsolete;
uint16_t file_mark_eom_ili_resv_sense_key;
uint8_t sense_info[4];
uint8_t additional_sense_len;
uint32_t csi;
uint8_t asc;
uint8_t ascq;
uint8_t fruc;
uint8_t sense_key_specific;
}__PACKED;
int ucs_scsi_send_inquiry(struct ufs_dev *dev);
int ucs_do_scsi_cmd(struct ufs_dev *dev, struct scsi_req_build_type *req);
int ucs_do_scsi_read(struct ufs_dev *dev, struct scsi_rdwr_req *req);
int ucs_do_scsi_write(struct ufs_dev *dev, struct scsi_rdwr_req *req);
int ucs_do_scsi_unmap(struct ufs_dev *dev, struct scsi_unmap_req *req);
/*
* ucs_do_sci_rpmb_read function takes a RPMB frame, sector address and number of
* blocks to be read from RPMB partition as input and returns one or more RPMB
* frames as response along with total length of the reponse. The response is then
* processed by upper layers.
*/
int ucs_do_scsi_rpmb_read(struct ufs_dev *dev, uint32_t *req_buf, uint32_t blk_cnt,
uint32_t *resp_buffer, uint32_t *response_length);
/* This function parses the first byte of the sense data and returns the sense key */
int parse_sense_key(uint32_t sense_data);
int ucs_do_request_sense(struct ufs_dev *dev, uint8_t lun);
#endif