예제 #1
0
/*
 * Function name:	tw_cli_scsi_complete
 * Description:		Completion routine for SCSI requests.
 *
 * Input:		req	-- ptr to CL internal request context
 * Output:		None
 * Return value:	None
 */
TW_VOID
tw_cli_scsi_complete(struct tw_cli_req_context *req)
{
	struct tw_cl_req_packet		*req_pkt =
		(struct tw_cl_req_packet *)(req->orig_req);
	struct tw_cl_scsi_req_packet	*scsi_req =
		&(req_pkt->gen_req_pkt.scsi_req);
	struct tw_cl_command_9k		*cmd =
		&(req->cmd_pkt->command.cmd_pkt_9k);
	struct tw_cl_command_header	*cmd_hdr;
	TW_UINT16			error;
	TW_UINT8			*cdb;

	tw_cli_dbg_printf(8, req->ctlr->ctlr_handle, tw_osl_cur_func(),
		"entered");

	scsi_req->scsi_status = cmd->status;
	if (! cmd->status)
		return;

	tw_cli_dbg_printf(1, req->ctlr->ctlr_handle, tw_osl_cur_func(),
		"req_id = 0x%x, status = 0x%x",
		GET_REQ_ID(cmd->lun_l4__req_id), cmd->status);

	cmd_hdr = &(req->cmd_pkt->cmd_hdr);
	error = cmd_hdr->status_block.error;
	if ((error == TWA_ERROR_LOGICAL_UNIT_NOT_SUPPORTED) ||
			(error == TWA_ERROR_UNIT_OFFLINE)) {
		if (GET_LUN_L4(cmd->lun_l4__req_id))
			req_pkt->status |= TW_CL_ERR_REQ_INVALID_LUN;
		else
			req_pkt->status |= TW_CL_ERR_REQ_INVALID_TARGET;
	} else {
		tw_cli_dbg_printf(2, req->ctlr->ctlr_handle,
			tw_osl_cur_func(),
			"cmd = %x %x %x %x %x %x %x",
			GET_OPCODE(cmd->res__opcode),
			GET_SGL_OFF(cmd->res__opcode),
			cmd->unit,
			cmd->lun_l4__req_id,
			cmd->status,
			cmd->sgl_offset,
			cmd->lun_h4__sgl_entries);

		cdb = (TW_UINT8 *)(cmd->cdb);
		tw_cli_dbg_printf(2, req->ctlr->ctlr_handle,
			tw_osl_cur_func(),
			"cdb = %x %x %x %x %x %x %x %x "
			"%x %x %x %x %x %x %x %x",
			cdb[0], cdb[1], cdb[2], cdb[3],
			cdb[4], cdb[5], cdb[6], cdb[7],
			cdb[8], cdb[9], cdb[10], cdb[11],
			cdb[12], cdb[13], cdb[14], cdb[15]);

#if       0
		/* 
		 * Print the error. Firmware doesn't yet support
		 * the 'Mode Sense' cmd.  Don't print if the cmd
		 * is 'Mode Sense', and the error is 'Invalid field
		 * in CDB'.
		 */
		if (! ((cdb[0] == 0x1A) && (error == 0x10D)))
			tw_cli_create_ctlr_event(req->ctlr,
				TW_CL_MESSAGE_SOURCE_CONTROLLER_ERROR,
				cmd_hdr);
#endif // 0
	}

	if (scsi_req->sense_data) {
		tw_osl_memcpy(scsi_req->sense_data, cmd_hdr->sense_data,
			TWA_SENSE_DATA_LENGTH);
		scsi_req->sense_len = TWA_SENSE_DATA_LENGTH;
		req_pkt->status |= TW_CL_ERR_REQ_AUTO_SENSE_VALID;
	}
	req_pkt->status |= TW_CL_ERR_REQ_SCSI_ERROR;
}
예제 #2
0
파일: tw_cl_misc.c 프로젝트: coyizumi/cs111
/*
 * Function name:	tw_cli_print_req_info
 * Description:		Prints CL internal details of a given request.
 *
 * Input:		req	-- ptr to CL internal request context
 * Output:		None
 * Return value:	None
 */
TW_VOID
tw_cl_print_req_info(struct tw_cl_req_handle *req_handle)
{
	struct tw_cli_req_context	*req = req_handle->cl_req_ctxt;
	struct tw_cli_ctlr_context	*ctlr = req->ctlr;
	struct tw_cl_ctlr_handle	*ctlr_handle = ctlr->ctlr_handle;
	struct tw_cl_command_packet	*cmd_pkt = req->cmd_pkt;
	struct tw_cl_command_9k		*cmd9k;
	union tw_cl_command_7k		*cmd7k;
	TW_UINT8			*cdb;
	TW_VOID				*sgl;
	TW_UINT32			sgl_entries;
	TW_UINT32			i;

	tw_cli_dbg_printf(0, ctlr_handle, tw_osl_cur_func(),
		"CL details for request:");
	tw_cli_dbg_printf(0, ctlr_handle, tw_osl_cur_func(),
		"req_handle = %p, ctlr = %p,\n"
		"cmd_pkt = %p, cmd_pkt_phys = 0x%llx,\n"
		"data = %p, length = 0x%x, data_phys = 0x%llx,\n"
		"state = 0x%x, flags = 0x%x, error = 0x%x,\n"
		"orig_req = %p, callback = %p, req_id = 0x%x,\n"
		"next_req = %p, prev_req = %p",
		req_handle, ctlr,
		cmd_pkt, req->cmd_pkt_phys,
		req->data, req->length, req->data_phys,
		req->state, req->flags, req->error_code,
		req->orig_req, req->tw_cli_callback, req->request_id,
		req->link.next, req->link.prev);

	if (req->flags & TW_CLI_REQ_FLAGS_9K) {
		cmd9k = &(cmd_pkt->command.cmd_pkt_9k);
		sgl = cmd9k->sg_list;
		sgl_entries = TW_CL_SWAP16(
			GET_SGL_ENTRIES(cmd9k->lun_h4__sgl_entries));
		tw_cli_dbg_printf(0, ctlr_handle, tw_osl_cur_func(),
			"9K cmd: opcode = 0x%x, unit = 0x%x, req_id = 0x%x,\n"
			"status = 0x%x, sgl_offset = 0x%x, sgl_entries = 0x%x",
			GET_OPCODE(cmd9k->res__opcode),
			cmd9k->unit,
			TW_CL_SWAP16(GET_REQ_ID(cmd9k->lun_l4__req_id)),
			cmd9k->status,
			cmd9k->sgl_offset,
			sgl_entries);

		cdb = (TW_UINT8 *)(cmd9k->cdb);
		tw_cli_dbg_printf(0, ctlr_handle, tw_osl_cur_func(),
			"CDB: %x %x %x %x %x %x %x %x"
			"%x %x %x %x %x %x %x %x",
			cdb[0], cdb[1], cdb[2], cdb[3],
			cdb[4], cdb[5], cdb[6], cdb[7],
			cdb[8], cdb[9], cdb[10], cdb[11],
			cdb[12], cdb[13], cdb[14], cdb[15]);
	} else {
		cmd7k = &(cmd_pkt->command.cmd_pkt_7k);
		sgl = cmd7k->param.sgl;
		sgl_entries = (cmd7k->generic.size -
			GET_SGL_OFF(cmd7k->generic.sgl_off__opcode)) /
			((ctlr->flags & TW_CL_64BIT_ADDRESSES) ? 3 : 2);
		tw_cli_dbg_printf(0, ctlr_handle, tw_osl_cur_func(),
			"7K cmd: opcode = 0x%x, sgl_offset = 0x%x,\n"
			"size = 0x%x, req_id = 0x%x, unit = 0x%x,\n"
			"status = 0x%x, flags = 0x%x, count = 0x%x",
			GET_OPCODE(cmd7k->generic.sgl_off__opcode),
			GET_SGL_OFF(cmd7k->generic.sgl_off__opcode),
			cmd7k->generic.size,
			TW_CL_SWAP16(cmd7k->generic.request_id),
			GET_UNIT(cmd7k->generic.host_id__unit),
			cmd7k->generic.status,
			cmd7k->generic.flags,
			TW_CL_SWAP16(cmd7k->generic.count));
	}

	tw_cli_dbg_printf(0, ctlr_handle, tw_osl_cur_func(), "SG entries:");

	if (ctlr->flags & TW_CL_64BIT_ADDRESSES) {
		struct tw_cl_sg_desc64 *sgl64 = (struct tw_cl_sg_desc64 *)sgl;

		for (i = 0; i < sgl_entries; i++) {
			tw_cli_dbg_printf(0, ctlr_handle, tw_osl_cur_func(),
				"0x%llx  0x%x",
				sgl64[i].address, sgl64[i].length);
		}
	} else {
		struct tw_cl_sg_desc32 *sgl32 = (struct tw_cl_sg_desc32 *)sgl;

		for (i = 0; i < sgl_entries; i++) {
			tw_cli_dbg_printf(0, ctlr_handle, tw_osl_cur_func(),
				"0x%x  0x%x",
				sgl32[i].address, sgl32[i].length);
		}
	}
}