Пример #1
0
int encdec_send_device_command(u64 cmd, u8 *send_data, u64 send_data_size,
	u8 *recv_data, u64 recv_data_size)
{
	u64 tag, status, ticks;
	int result;

	memset(encdec_buf, 0, ENCDEC_DMA_SIZE);

	memcpy(encdec_buf, send_data, send_data_size);

	result = lv1_storage_send_device_command(ENCDEC_DEV_ID, cmd,
		encdec_buf_lpar_addr, send_data_size,
		encdec_buf_lpar_addr + send_data_size, recv_data_size, &tag);
	if (result != 0)
		return result;

	for (;;)
	{
		result = lv1_storage_check_async_status(ENCDEC_DEV_ID, tag, &status);
		if (result != 0)
			continue;

		if (status == 0)
			break;

		ticks = TB_TICKS_PER_SEC / 10;

		sleep(ticks);
	}

	memcpy(recv_data, encdec_buf + send_data_size, recv_data_size);

	return 0;
}
Пример #2
0
/**
 *	ps3stor_send_command - send a device command to a storage device
 *	@dev: Pointer to a struct ps3_storage_device
 *	@cmd: Command number
 *	@arg1: First command argument
 *	@arg2: Second command argument
 *	@arg3: Third command argument
 *	@arg4: Fourth command argument
 *
 *	Returns 0 for success, -1 in case of failure to submit the command, or
 *	an LV1 status value in case of other errors
 */
u64 ps3stor_send_command(struct ps3_storage_device *dev, u64 cmd, u64 arg1,
			 u64 arg2, u64 arg3, u64 arg4)
{
	int res;

	dev_dbg(&dev->sbd.core, "%s:%u: send device command 0x%lx\n", __func__,
		__LINE__, cmd);

	init_completion(&dev->done);

	res = lv1_storage_send_device_command(dev->sbd.dev_id, cmd, arg1,
					      arg2, arg3, arg4, &dev->tag);
	if (res) {
		dev_err(&dev->sbd.core,
			"%s:%u: send_device_command 0x%lx failed %d\n",
			__func__, __LINE__, cmd, res);
		return -1;
	}

	wait_for_completion(&dev->done);
	if (dev->lv1_status) {
		dev_dbg(&dev->sbd.core, "%s:%u: command 0x%lx failed 0x%lx\n",
			__func__, __LINE__, cmd, dev->lv1_status);
		return dev->lv1_status;
	}

	dev_dbg(&dev->sbd.core, "%s:%u: command 0x%lx completed\n", __func__,
		__LINE__, cmd);

	return 0;
}
Пример #3
0
static int ps3rom_atapi_request(struct ps3_storage_device *dev,
				struct scsi_cmnd *cmd)
{
	struct lv1_atapi_cmnd_block atapi_cmnd;
	unsigned char opcode = cmd->cmnd[0];
	int res;
	u64 lpar;

	dev_dbg(&dev->sbd.core, "%s:%u: send ATAPI command 0x%02x\n", __func__,
		__LINE__, opcode);

	memset(&atapi_cmnd, 0, sizeof(struct lv1_atapi_cmnd_block));
	memcpy(&atapi_cmnd.pkt, cmd->cmnd, 12);
	atapi_cmnd.pktlen = 12;
	atapi_cmnd.block_size = 1; /* transfer size is block_size * blocks */
	atapi_cmnd.blocks = atapi_cmnd.arglen = scsi_bufflen(cmd);
	atapi_cmnd.buffer = dev->bounce_lpar;

	switch (cmd->sc_data_direction) {
	case DMA_FROM_DEVICE:
		if (scsi_bufflen(cmd) >= CD_FRAMESIZE)
			atapi_cmnd.proto = DMA_PROTO;
		else
			atapi_cmnd.proto = PIO_DATA_IN_PROTO;
		atapi_cmnd.in_out = DIR_READ;
		break;

	case DMA_TO_DEVICE:
		if (scsi_bufflen(cmd) >= CD_FRAMESIZE)
			atapi_cmnd.proto = DMA_PROTO;
		else
			atapi_cmnd.proto = PIO_DATA_OUT_PROTO;
		atapi_cmnd.in_out = DIR_WRITE;
		scsi_sg_copy_to_buffer(cmd, dev->bounce_buf, dev->bounce_size);
		break;

	default:
		atapi_cmnd.proto = NON_DATA_PROTO;
		break;
	}

	lpar = ps3_mm_phys_to_lpar(__pa(&atapi_cmnd));
	res = lv1_storage_send_device_command(dev->sbd.dev_id,
					      LV1_STORAGE_SEND_ATAPI_COMMAND,
					      lpar, sizeof(atapi_cmnd),
					      atapi_cmnd.buffer,
					      atapi_cmnd.arglen, &dev->tag);
	if (res == LV1_DENIED_BY_POLICY) {
		dev_dbg(&dev->sbd.core,
			"%s:%u: ATAPI command 0x%02x denied by policy\n",
			__func__, __LINE__, opcode);
		return DID_ERROR << 16;
	}

	if (res) {
		dev_err(&dev->sbd.core,
			"%s:%u: ATAPI command 0x%02x failed %d\n", __func__,
			__LINE__, opcode, res);
		return DID_ERROR << 16;
	}

	return 0;
}