Пример #1
0
int ucs_scsi_send_inquiry(struct ufs_dev *dev)
{
	STACKBUF_DMA_ALIGN(cdb_param, SCSI_CDB_PARAM_LEN);
	STACKBUF_DMA_ALIGN(param, SCSI_INQUIRY_LEN);
	struct scsi_req_build_type req_upiu;

	memset(cdb_param, 0, SCSI_CDB_PARAM_LEN);
	cdb_param[0] = SCSI_CMD_INQUIRY;
	cdb_param[3] = sizeof(param)>> 8;
	cdb_param[4] = sizeof(param);

	/* Flush cdb to memory. */
	dsb();
	arch_invalidate_cache_range((addr_t) cdb_param, SCSI_CDB_PARAM_LEN);

	memset(&req_upiu, 0 , sizeof(struct scsi_req_build_type));

	req_upiu.cdb			   = (addr_t) cdb_param;
	req_upiu.data_buffer_addr  = (addr_t) param;
	req_upiu.data_len          = SCSI_INQUIRY_LEN;
	req_upiu.flags			   = UPIU_FLAGS_READ;
	req_upiu.lun			   = 0;
	req_upiu.dd			       = UTRD_TARGET_TO_SYSTEM;

	if (ucs_do_scsi_cmd(dev, &req_upiu))
	{
		dprintf(CRITICAL, "Failed to send SCSI inquiry\n");
		return -UFS_FAILURE;
	}

	/* Flush buffer. */
	arch_invalidate_cache_range((addr_t) param, SCSI_INQUIRY_LEN);

	return UFS_SUCCESS;
}
Пример #2
0
int ucs_do_scsi_unmap(struct ufs_dev *dev, struct scsi_unmap_req *req)
{
	STACKBUF_DMA_ALIGN(cdb_param, SCSI_CDB_PARAM_LEN);
	STACKBUF_DMA_ALIGN(param, sizeof(struct unmap_param_list));
	struct scsi_req_build_type req_upiu;
	struct unmap_param_list *param_list;
	struct unmap_blk_desc *blk_desc;

	param_list                    = (struct unmap_param_list *)param;
	param_list->data_len          = (sizeof(struct unmap_param_list) - 1) << 0x8; /* n-1 */

	param_list->blk_desc_data_len = sizeof(struct unmap_blk_desc) << 0x8;


	blk_desc = &(param_list->blk_desc);

	blk_desc->lba      = BE64(req->start_lba);
	blk_desc->num_blks = BE32(req->num_blocks);

	memset((void*)cdb_param, 0, SCSI_CDB_PARAM_LEN);
	cdb_param[0] = SCSI_CMD_UNMAP;
	cdb_param[1] = 0;                    /*ANCHOR = 0 for UFS*/
	cdb_param[6] = 0;                    /*Group No = 0*/
	cdb_param[7] = 0;                    /* Param list length is 1, we erase 1 contiguous blk*/
	cdb_param[8] = sizeof(struct unmap_param_list);
	cdb_param[9] = 0;

        /* Flush cdb to memory. */
	dsb();
	arch_invalidate_cache_range((addr_t) cdb_param, SCSI_CDB_PARAM_LEN);

	memset((void*)&req_upiu, 0 , sizeof(struct scsi_req_build_type));

	req_upiu.cdb                       = (addr_t) cdb_param;
	req_upiu.data_buffer_addr          = (addr_t) param;
	req_upiu.data_len                  = sizeof(struct unmap_param_list);
	req_upiu.flags                     = UPIU_FLAGS_WRITE;
	req_upiu.lun                       = req->lun;
	req_upiu.dd                        = UTRD_SYSTEM_TO_TARGET;

	if (ucs_do_scsi_cmd(dev, &req_upiu))
	{
		dprintf(CRITICAL, "Failed to send SCSI unmap command \n");
		return -UFS_FAILURE;
	}

	/* Flush buffer. */
	arch_invalidate_cache_range((addr_t) param, SCSI_INQUIRY_LEN);

	return UFS_SUCCESS;
}
Пример #3
0
int dme_read_unit_desc(struct ufs_dev *dev, uint8_t index)
{
	STACKBUF_DMA_ALIGN(unit_desc, sizeof(struct ufs_unit_desc));
	struct ufs_unit_desc           *desc = (struct ufs_unit_desc *) unit_desc;
	struct utp_query_req_upiu_type query = {UPIU_QUERY_OP_READ_DESCRIPTOR,
											UFS_DESC_IDN_UNIT,
											index,
											0,
											(addr_t) unit_desc,
											sizeof(struct ufs_unit_desc)};

	if (dme_send_query_upiu(dev, &query))
	{
		dprintf(CRITICAL, "%s:%d DME Read Unit Descriptor request failed\n", __func__, __LINE__);
		return -UFS_FAILURE;
	}
	/* Flush buffer. */
	arch_invalidate_cache_range((addr_t) desc, sizeof(struct ufs_unit_desc));

	dev->lun_cfg[index].logical_blk_cnt = BE64(desc->logical_blk_cnt);

	dev->lun_cfg[index].erase_blk_size = BE32(desc->erase_blk_size);

	// use only the lower 32 bits for rpmb partition size
	if (index == UFS_WLUN_RPMB)
		dev->rpmb_num_blocks = BE32(desc->logical_blk_cnt >> 32);

	return UFS_SUCCESS;
}
Пример #4
0
int dme_set_fpoweronwpen(struct ufs_dev *dev)
{
	STACKBUF_DMA_ALIGN(result, sizeof(uint32_t));
	uint32_t try_again                        = DME_FPOWERONWPEN_RETRIES;
	struct utp_query_req_upiu_type read_query = {UPIU_QUERY_OP_READ_FLAG,
                                                 UFS_IDX_fPowerOnWPEn,
                                                 0,
                                                 0,
                                                 (addr_t) result,
                                                 sizeof(uint32_t)};
	struct utp_query_req_upiu_type set_query  = {UPIU_QUERY_OP_SET_FLAG,
                                                 UFS_IDX_fPowerOnWPEn,
                                                 0,
                                                 0,
                                                 (addr_t) result,
                                                 sizeof(uint32_t)};


	if (dme_send_query_upiu(dev, &read_query))
	{
		dprintf(CRITICAL, "%s:%d DME Power On Write Read Request failed\n", __func__, __LINE__);
		return -UFS_FAILURE;
	}

	arch_invalidate_cache_range((addr_t) result, sizeof(uint32_t));

	if (*result == 1)
		goto utp_set_fpoweronwpen_done;

	do
	{
		try_again--;
		dprintf(CRITICAL, "Power on Write Protect request failed. Retrying again.\n");

		if (dme_send_query_upiu(dev, &set_query))
		{
			dprintf(CRITICAL, "%s:%d DME Power On Write Set Request failed\n", __func__, __LINE__);
			return -UFS_FAILURE;
		}

		if (dme_send_query_upiu(dev, &read_query))
		{
			dprintf(CRITICAL, "%s:%d DME Power On Write Read Request failed\n", __func__, __LINE__);
			return -UFS_FAILURE;
		}

		if (*result == 1)
			break;
	} while (try_again);

utp_set_fpoweronwpen_done:
	dprintf(INFO,"Power on Write Protect status: %u\n", *result);
	return UFS_SUCCESS;
}
Пример #5
0
int dme_set_fdeviceinit(struct ufs_dev *dev)
{
	STACKBUF_DMA_ALIGN(result, sizeof(uint32_t));
	uint32_t try_again                        = DME_FDEVICEINIT_RETRIES;
	struct utp_query_req_upiu_type read_query = {UPIU_QUERY_OP_READ_FLAG,
												 UFS_IDX_fDeviceInit,
												 0,
												 0,
												 (addr_t) result,
												 sizeof(uint32_t)};
	struct utp_query_req_upiu_type set_query  = {UPIU_QUERY_OP_SET_FLAG,
												 UFS_IDX_fDeviceInit,
												 0,
												 0,
												 (addr_t) result,
												 sizeof(uint32_t)};


	if (dme_send_query_upiu(dev, &read_query))
	{
		dprintf(CRITICAL, "%s:%d DME Device Init Read request failed\n", __func__, __LINE__);
		return -UFS_FAILURE;
	}

	arch_invalidate_cache_range((addr_t) result, sizeof(uint32_t));

	if (*result == 1)
		goto utp_set_fdeviceinit_done;

	do
	{
		try_again--;

		if (dme_send_query_upiu(dev, &set_query))
		{
			dprintf(CRITICAL, "%s:%d DME Device Init Set request failed\n", __func__, __LINE__);
			return -UFS_FAILURE;
		}

		if (dme_send_query_upiu(dev, &read_query))
		{
			dprintf(CRITICAL, "%s:%d DME Device Init Read request failed\n", __func__, __LINE__);
			return -UFS_FAILURE;
		}

		if (*result == 1)
			break;
	} while (try_again);

utp_set_fdeviceinit_done:
	return UFS_SUCCESS;
}
Пример #6
0
void fastboot_info(const char *reason)
{
	STACKBUF_DMA_ALIGN(response, MAX_RSP_SIZE);

	if (fastboot_state != STATE_COMMAND)
		return;

	if (reason == 0)
		return;

	snprintf(response, MAX_RSP_SIZE, "INFO%s", reason);

	usb_write(response, strlen(response));
}
Пример #7
0
int dme_read_device_desc(struct ufs_dev *dev)
{
	STACKBUF_DMA_ALIGN(dev_desc, sizeof(struct ufs_dev_desc));
	STACKBUF_DMA_ALIGN(desc, sizeof(struct ufs_string_desc));
	struct ufs_dev_desc            *device_desc = (struct ufs_dev_desc *) dev_desc;
	struct ufs_string_desc         *str_desc    = (struct ufs_string_desc *) desc;
	struct utp_query_req_upiu_type query = {UPIU_QUERY_OP_READ_DESCRIPTOR,
											UFS_DESC_IDN_DEVICE,
											0,
											0,
											(addr_t) dev_desc,
											sizeof(struct ufs_dev_desc)};

	if (dme_send_query_upiu(dev, &query))
	{
		dprintf(CRITICAL, "%s:%d DME Read Device Descriptor request failed\n", __func__, __LINE__);
		return -UFS_FAILURE;
	}

	/* Flush buffer. */
	arch_invalidate_cache_range((addr_t) device_desc, sizeof(struct ufs_dev_desc));

	/* Store all relevant data */
	dev->num_lus = device_desc->num_lu;

	/* Get serial number for the device based on the string index. */
	if (dme_read_string_desc(dev, device_desc->serial_num, (struct ufs_string_desc *) desc))
		return -UFS_FAILURE;

	/* Flush buffer. */
	arch_invalidate_cache_range((addr_t) str_desc, sizeof(struct ufs_string_desc));

	dev->serial_num = dme_parse_serial_no(str_desc);

	return UFS_SUCCESS;
}
Пример #8
0
void fastboot_ack(const char *code, const char *reason)
{
	STACKBUF_DMA_ALIGN(response, MAX_RSP_SIZE);

	if (fastboot_state != STATE_COMMAND)
		return;

	if (reason == 0)
		reason = "";

	snprintf(response, MAX_RSP_SIZE, "%s%s", code, reason);
	fastboot_state = STATE_COMPLETE;

	usb_write(response, strlen(response));

}
Пример #9
0
static int ucs_do_request_sense(struct ufs_dev *dev)
{
	STACKBUF_DMA_ALIGN(cdb, sizeof(struct scsi_sense_cdb));
	struct scsi_req_build_type req_upiu;
	struct scsi_sense_cdb      *cdb_param;
	uint8_t                    buf[SCSI_SENSE_BUF_LEN];

	cdb_param = cdb;

	memset(cdb, 0, sizeof(struct scsi_sense_cdb));

	cdb_param->opcode    = SCSI_CMD_SENSE_REQ;
	cdb_param->alloc_len = SCSI_SENSE_BUF_LEN;

	/* Flush cdb to memory. */
	dsb();
	arch_invalidate_cache_range((addr_t) cdb_param, SCSI_CDB_PARAM_LEN);

	memset(&req_upiu, 0 , sizeof(struct scsi_req_build_type));

	req_upiu.cdb			   = (addr_t) cdb_param;
	req_upiu.data_buffer_addr  = (addr_t) buf;
	req_upiu.data_len          = SCSI_SENSE_BUF_LEN;
	req_upiu.flags			   = UPIU_FLAGS_READ;
	req_upiu.lun			   = 0;
	req_upiu.dd			       = UTRD_TARGET_TO_SYSTEM;

	if (ucs_do_scsi_cmd(dev, &req_upiu))
	{
		dprintf(CRITICAL, "ucs_do_request_sense: failed\n");
		return -UFS_FAILURE;
	}

	/* Flush buffer. */
	arch_invalidate_cache_range((addr_t) buf, SCSI_INQUIRY_LEN);

	dump_sense_buffer(buf, SCSI_SENSE_BUF_LEN);

	return UFS_SUCCESS;
}
Пример #10
0
int dme_read_config_desc(struct ufs_dev *dev)
{
	STACKBUF_DMA_ALIGN(desc, sizeof(struct ufs_config_desc));
	struct ufs_config_desc         *config_desc = (struct ufs_config_desc *)desc;
	struct utp_query_req_upiu_type query = {UPIU_QUERY_OP_READ_DESCRIPTOR,
											UFS_DESC_IDN_CONFIGURATION,
											0,
											0,
											(addr_t) config_desc,
											sizeof(struct ufs_config_desc)};

	if (dme_send_query_upiu(dev, &query))
	{
		dprintf(CRITICAL, "%s:%d DME Read Config Descriptor request failed\n", __func__, __LINE__);
		return -UFS_FAILURE;
	}

	/* Flush buffer. */
	arch_invalidate_cache_range((addr_t) config_desc, sizeof(struct ufs_config_desc));

	return UFS_SUCCESS;
}
Пример #11
0
int dme_read_geo_desc(struct ufs_dev *dev)
{
	struct ufs_geometry_desc *desc;
	STACKBUF_DMA_ALIGN(geometry_desc, sizeof(struct ufs_geometry_desc));
	desc = (struct ufs_geometry_desc *) geometry_desc;
	struct utp_query_req_upiu_type query = {UPIU_QUERY_OP_READ_DESCRIPTOR,
											UFS_DESC_IDN_GEOMETRY,
											0,
											0,
											(addr_t) geometry_desc,
											sizeof(struct ufs_geometry_desc)};

	if (dme_send_query_upiu(dev, &query))
	{
		dprintf(CRITICAL, "%s:%d DME Read Geometry Descriptor request failed\n", __func__, __LINE__);
		return -UFS_FAILURE;
	}

	// Flush buffer.
	arch_invalidate_cache_range((addr_t) desc, sizeof(struct ufs_geometry_desc));
	dev->rpmb_rw_size = desc->rpmb_read_write_size;
	return UFS_SUCCESS;
}
Пример #12
0
static void cmd_download(const char *arg, void *data, unsigned sz)
{
	STACKBUF_DMA_ALIGN(response, MAX_RSP_SIZE);
	unsigned len = hex2unsigned(arg);
	int r;

	download_size = 0;
	if (len > download_max) {
		fastboot_fail("data too large");
		return;
	}

	snprintf(response, MAX_RSP_SIZE, "DATA%08x", len);
	if (usb_write(response, strlen(response)) < 0)
		return;

	r = usb_read(download_base, len);
	if ((r < 0) || ((unsigned) r != len)) {
		fastboot_state = STATE_ERROR;
		return;
	}
	download_size = len;
	fastboot_okay("");
}
Пример #13
0
int dme_set_fpurgeenable(struct ufs_dev *dev)
{
	STACKBUF_DMA_ALIGN(result, sizeof(uint32_t));
	STACKBUF_DMA_ALIGN(status, sizeof(uint32_t));
	uint32_t try_again                        = DME_BPURGESTATUS_RETRIES;
	struct utp_query_req_upiu_type set_query  = {UPIU_QUERY_OP_SET_FLAG,
												 UFS_IDX_fPurgeEn,
												 0,
												 0,
												 (addr_t) result,
												 sizeof(uint32_t)};
	struct utp_query_req_upiu_type read_query = {UPIU_QUERY_OP_READ_ATTRIBUTE,
												 UFS_IDX_bPurgeStatus,
												 0,
												 0,
												 (addr_t)status,
												 sizeof(uint32_t)};

	if (dme_send_query_upiu(dev, &set_query))
	{
		dprintf(CRITICAL, "%s:%d DME Purge Enable failed\n", __func__, __LINE__);
		return -UFS_FAILURE;
	}

	arch_invalidate_cache_range((addr_t) result, sizeof(uint32_t));
	dprintf(INFO, "%s:%d Purge enable status: %u\n", __func__,__LINE__, *result);

	do {
		*status = 0;
		arch_invalidate_cache_range((addr_t) status, sizeof(uint32_t));
		if (dme_send_query_upiu(dev, &read_query))
		{
			dprintf(CRITICAL, "%s:%d DME Purge Status Read failed\n", __func__, __LINE__);
			return -UFS_FAILURE;
		}

		switch (*status)
		{

			case 0x0:
#ifdef DEBUG_UFS
				dprintf(INFO, "%s:%d Purge operation returning to ufs_erase. Purge Status 0x0\n", __func__, __LINE__);
#endif
				return UFS_SUCCESS;
			case 0x3:
#ifdef DEBUG_UFS
				dprintf(INFO, "%s:%d Purge operation has completed. Purge Status:0x3\n", __func__, __LINE__);
#endif
				// next read of status will move to 0
				continue;
			case 0x1:
#ifdef DEBUG_UFS
				dprintf(INFO, "%s:%d Purge operation is still in progress.. Retrying\n", __func__, __LINE__);
#endif
				try_again--;
				continue;
			case 0x2:
				dprintf(CRITICAL, "%s:%d Purge operation stopped prematurely\n", __func__, __LINE__);
				return -UFS_FAILURE;
			case 0x4:
				dprintf(CRITICAL, "%s:%d Purge operation failed due to logical unit queue not empty\n", __func__, __LINE__);
				return -UFS_FAILURE;
			case 0x5:
				dprintf(CRITICAL, "%s:%d Purge operation general failure\n", __func__, __LINE__);
				return -UFS_FAILURE;
		}
	} while((*status == 0x1 || *status == 0x3) && try_again);

	// should not come here
	dprintf(CRITICAL, "%s:%d Purge operation timed out after checking status %d times\n", __func__, __LINE__, DME_BPURGESTATUS_RETRIES);
	return -UFS_FAILURE;
}
Пример #14
0
int ucs_do_scsi_read(struct ufs_dev *dev, struct scsi_rdwr_req *req)
{
	STACKBUF_DMA_ALIGN(cdb, sizeof(struct scsi_rdwr_cdb));
	struct scsi_req_build_type     req_upiu;
	struct scsi_rdwr_cdb           *cdb_param;
	uint32_t                       blks_remaining;
	uint16_t                       blks_to_transfer;
	uint64_t                       bytes_to_transfer;
	uint32_t                       start_blk;
	uint32_t                       buf;

	blks_remaining = req->num_blocks;
	buf            = req->data_buffer_base;
	start_blk      = req->start_lba;

	cdb_param = (struct scsi_rdwr_cdb*) cdb;
	while (blks_remaining)
	{
		if (blks_remaining <= SCSI_MAX_DATA_TRANS_BLK_LEN)
		{
			blks_to_transfer = blks_remaining;
			blks_remaining   = 0;
		}
		else
		{
			blks_to_transfer = SCSI_MAX_DATA_TRANS_BLK_LEN;
			blks_remaining  -= SCSI_MAX_DATA_TRANS_BLK_LEN;
		}

		bytes_to_transfer = blks_to_transfer * UFS_DEFAULT_SECTORE_SIZE;

		memset(cdb_param, 0, sizeof(struct scsi_rdwr_cdb));
		cdb_param->opcode    = SCSI_CMD_READ10;
		cdb_param->cdb1      = SCSI_READ_WRITE_10_CDB1(0, 0, 1, 0);
		cdb_param->lba       = BE32(start_blk);
		cdb_param->trans_len = BE16(blks_to_transfer);


		dsb();
		arch_clean_invalidate_cache_range((addr_t) cdb_param, sizeof(struct scsi_rdwr_cdb));

		memset(&req_upiu, 0 , sizeof(struct scsi_req_build_type));

		req_upiu.cdb               = (addr_t) cdb_param;
		req_upiu.data_buffer_addr  = buf;
		req_upiu.data_len = bytes_to_transfer;
		req_upiu.flags             = UPIU_FLAGS_READ;
		req_upiu.lun               = req->lun;
		req_upiu.dd                = UTRD_TARGET_TO_SYSTEM;

		if (ucs_do_scsi_cmd(dev, &req_upiu))
		{
			dprintf(CRITICAL, "ucs_do_scsi_read: failed\n");
			return -UFS_FAILURE;
		}

		buf       += bytes_to_transfer;
		start_blk += SCSI_MAX_DATA_TRANS_BLK_LEN;
	}

	return UFS_SUCCESS;
}