145039663SJohn Forte /*
245039663SJohn Forte  * CDDL HEADER START
345039663SJohn Forte  *
445039663SJohn Forte  * The contents of this file are subject to the terms of the
545039663SJohn Forte  * Common Development and Distribution License (the "License").
645039663SJohn Forte  * You may not use this file except in compliance with the License.
745039663SJohn Forte  *
845039663SJohn Forte  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
945039663SJohn Forte  * or http://www.opensolaris.org/os/licensing.
1045039663SJohn Forte  * See the License for the specific language governing permissions
1145039663SJohn Forte  * and limitations under the License.
1245039663SJohn Forte  *
1345039663SJohn Forte  * When distributing Covered Code, include this CDDL HEADER in each
1445039663SJohn Forte  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1545039663SJohn Forte  * If applicable, add the following below this CDDL HEADER, with the
1645039663SJohn Forte  * fields enclosed by brackets "[]" replaced with your own identifying
1745039663SJohn Forte  * information: Portions Copyright [yyyy] [name of copyright owner]
1845039663SJohn Forte  *
1945039663SJohn Forte  * CDDL HEADER END
2045039663SJohn Forte  */
2145039663SJohn Forte /*
2291159e90SJohn Forte  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
23*ef3b9e2fSDan McDonald  * Copyright 2013, Nexenta Systems, Inc. All rights reserved.
2445039663SJohn Forte  */
2545039663SJohn Forte 
2645039663SJohn Forte #include <sys/cpuvar.h>
2745039663SJohn Forte #include <sys/types.h>
2845039663SJohn Forte #include <sys/conf.h>
2945039663SJohn Forte #include <sys/file.h>
3045039663SJohn Forte #include <sys/ddi.h>
3145039663SJohn Forte #include <sys/sunddi.h>
3245039663SJohn Forte #include <sys/modctl.h>
3345039663SJohn Forte #include <sys/sysmacros.h>
3445039663SJohn Forte 
3545039663SJohn Forte #include <sys/socket.h>
3645039663SJohn Forte #include <sys/strsubr.h>
3745039663SJohn Forte #include <sys/door.h>
3845039663SJohn Forte 
3945039663SJohn Forte #include <sys/stmf.h>
4045039663SJohn Forte #include <sys/stmf_ioctl.h>
4145039663SJohn Forte #include <sys/portif.h>
424558d122SViswanathan Kannappan 
434558d122SViswanathan Kannappan #include "pppt.h"
4445039663SJohn Forte 
4545039663SJohn Forte static void pppt_msg_tgt_register(stmf_ic_msg_t *reg_port);
4645039663SJohn Forte 
4745039663SJohn Forte static void pppt_msg_tgt_deregister(stmf_ic_msg_t *msg);
4845039663SJohn Forte 
4945039663SJohn Forte static void pppt_msg_session_destroy(stmf_ic_msg_t *msg);
5045039663SJohn Forte 
5145039663SJohn Forte static void pppt_msg_scsi_cmd(stmf_ic_msg_t *msg);
5245039663SJohn Forte 
5345039663SJohn Forte static void pppt_msg_data_xfer_done(stmf_ic_msg_t *msg);
5445039663SJohn Forte 
5545039663SJohn Forte static void pppt_msg_handle_status(stmf_ic_msg_t *msg);
5645039663SJohn Forte 
5745039663SJohn Forte void
5845039663SJohn Forte pppt_msg_rx(stmf_ic_msg_t *msg)
5945039663SJohn Forte {
6045039663SJohn Forte 	switch (msg->icm_msg_type) {
6145039663SJohn Forte 	case STMF_ICM_REGISTER_PROXY_PORT:
6245039663SJohn Forte 		pppt_msg_tgt_register(msg);
6345039663SJohn Forte 		break;
6445039663SJohn Forte 	case STMF_ICM_DEREGISTER_PROXY_PORT:
6545039663SJohn Forte 		pppt_msg_tgt_deregister(msg);
6645039663SJohn Forte 		break;
6745039663SJohn Forte 	case STMF_ICM_SESSION_CREATE:
6845039663SJohn Forte 		pppt_msg_tx_status(msg, STMF_NOT_SUPPORTED);
6945039663SJohn Forte 		stmf_ic_msg_free(msg);
7045039663SJohn Forte 		break;
7145039663SJohn Forte 	case STMF_ICM_SESSION_DESTROY:
7245039663SJohn Forte 		pppt_msg_session_destroy(msg);
7345039663SJohn Forte 		break;
7445039663SJohn Forte 	case STMF_ICM_SCSI_CMD:
7545039663SJohn Forte 		pppt_msg_scsi_cmd(msg);
7645039663SJohn Forte 		break;
7745039663SJohn Forte 	case STMF_ICM_SCSI_DATA_XFER_DONE:
7845039663SJohn Forte 		pppt_msg_data_xfer_done(msg);
7945039663SJohn Forte 		break;
8045039663SJohn Forte 	case STMF_ICM_SCSI_DATA:
8145039663SJohn Forte 		/* Ignore, all proxy data will be immediate for now */
8245039663SJohn Forte 		pppt_msg_tx_status(msg, STMF_NOT_SUPPORTED);
8345039663SJohn Forte 		stmf_ic_msg_free(msg);
8445039663SJohn Forte 		break;
8545039663SJohn Forte 	case STMF_ICM_STATUS:
8645039663SJohn Forte 		pppt_msg_handle_status(msg);
8745039663SJohn Forte 		break;
8845039663SJohn Forte 	default:
8945039663SJohn Forte 		/* Other message types are not allowed */
9045039663SJohn Forte 		ASSERT(0);
9145039663SJohn Forte 		break;
9245039663SJohn Forte 	}
9345039663SJohn Forte }
9445039663SJohn Forte 
9545039663SJohn Forte void
9645039663SJohn Forte pppt_msg_tx_status(stmf_ic_msg_t *orig_msg, stmf_status_t status)
9745039663SJohn Forte {
9845039663SJohn Forte 	stmf_ic_msg_t	*msg;
9945039663SJohn Forte 
10045039663SJohn Forte 	/*
10145039663SJohn Forte 	 * If TX of status fails it should be treated the same as a loss of
10245039663SJohn Forte 	 * connection.  We expect the remote node to handle it.
10345039663SJohn Forte 	 */
10445039663SJohn Forte 	msg = stmf_ic_status_msg_alloc(status, orig_msg->icm_msg_type,
10545039663SJohn Forte 	    orig_msg->icm_msgid);
10645039663SJohn Forte 
10745039663SJohn Forte 	if (msg != NULL) {
10845039663SJohn Forte 		(void) stmf_ic_tx_msg(msg);
10945039663SJohn Forte 	}
11045039663SJohn Forte }
11145039663SJohn Forte 
11245039663SJohn Forte static void
11345039663SJohn Forte pppt_msg_tgt_register(stmf_ic_msg_t *msg)
11445039663SJohn Forte {
11545039663SJohn Forte 	stmf_ic_reg_port_msg_t	*reg_port;
11645039663SJohn Forte 	pppt_tgt_t		*result;
11745039663SJohn Forte 	stmf_status_t		stmf_status;
11845039663SJohn Forte 
11945039663SJohn Forte 	reg_port = msg->icm_msg;
12045039663SJohn Forte 
12145039663SJohn Forte 	PPPT_GLOBAL_LOCK();
12245039663SJohn Forte 	if (pppt_global.global_svc_state != PSS_ENABLED) {
12345039663SJohn Forte 		stmf_status = STMF_FAILURE;
12445039663SJohn Forte 		PPPT_INC_STAT(es_tgt_reg_svc_disabled);
12545039663SJohn Forte 		goto pppt_register_tgt_done;
12645039663SJohn Forte 	}
12745039663SJohn Forte 
12845039663SJohn Forte 	/*
12945039663SJohn Forte 	 * For now we assume that the marshall/unmarshall code is responsible
13045039663SJohn Forte 	 * for validating the message length and ensuring the resulting
13145039663SJohn Forte 	 * request structure is self consistent.  Make sure this
13245039663SJohn Forte 	 * target doesn't already exist.
13345039663SJohn Forte 	 */
13445039663SJohn Forte 	if ((result = pppt_tgt_lookup_locked(reg_port->icrp_port_id)) != NULL) {
13545039663SJohn Forte 		stmf_status = STMF_ALREADY;
13645039663SJohn Forte 		PPPT_INC_STAT(es_tgt_reg_duplicate);
13745039663SJohn Forte 		goto pppt_register_tgt_done;
13845039663SJohn Forte 	}
13945039663SJohn Forte 
14045039663SJohn Forte 	result = pppt_tgt_create(reg_port, &stmf_status);
14145039663SJohn Forte 
14245039663SJohn Forte 	if (result == NULL) {
14345039663SJohn Forte 		stmf_status = STMF_TARGET_FAILURE;
14445039663SJohn Forte 		PPPT_INC_STAT(es_tgt_reg_create_fail);
14545039663SJohn Forte 		goto pppt_register_tgt_done;
14645039663SJohn Forte 	}
14745039663SJohn Forte 
14845039663SJohn Forte 	avl_add(&pppt_global.global_target_list, result);
14945039663SJohn Forte 
15045039663SJohn Forte 	stmf_status = STMF_SUCCESS;
15145039663SJohn Forte 
15245039663SJohn Forte pppt_register_tgt_done:
15345039663SJohn Forte 	PPPT_GLOBAL_UNLOCK();
15445039663SJohn Forte 	pppt_msg_tx_status(msg, stmf_status);
15545039663SJohn Forte 	stmf_ic_msg_free(msg);
15645039663SJohn Forte }
15745039663SJohn Forte 
15845039663SJohn Forte static void
15945039663SJohn Forte pppt_msg_tgt_deregister(stmf_ic_msg_t *msg)
16045039663SJohn Forte {
16145039663SJohn Forte 	stmf_ic_dereg_port_msg_t	*dereg_port;
16245039663SJohn Forte 	stmf_status_t			stmf_status;
16345039663SJohn Forte 	pppt_tgt_t			*tgt;
16445039663SJohn Forte 
16545039663SJohn Forte 	PPPT_GLOBAL_LOCK();
16645039663SJohn Forte 	if (pppt_global.global_svc_state != PSS_ENABLED) {
16745039663SJohn Forte 		PPPT_GLOBAL_UNLOCK();
16845039663SJohn Forte 		stmf_status = STMF_FAILURE;
16945039663SJohn Forte 		PPPT_INC_STAT(es_tgt_dereg_svc_disabled);
17045039663SJohn Forte 		goto pppt_deregister_tgt_done;
17145039663SJohn Forte 	}
17245039663SJohn Forte 
17345039663SJohn Forte 	dereg_port = msg->icm_msg;
17445039663SJohn Forte 
17545039663SJohn Forte 	/* Lookup target */
17645039663SJohn Forte 	if ((tgt = pppt_tgt_lookup_locked(dereg_port->icdp_port_id)) == NULL) {
17745039663SJohn Forte 		PPPT_GLOBAL_UNLOCK();
17845039663SJohn Forte 		stmf_status = STMF_NOT_FOUND;
17945039663SJohn Forte 		PPPT_INC_STAT(es_tgt_dereg_not_found);
18045039663SJohn Forte 		goto pppt_deregister_tgt_done;
18145039663SJohn Forte 	}
18245039663SJohn Forte 	avl_remove(&pppt_global.global_target_list, tgt);
18345039663SJohn Forte 	pppt_tgt_async_delete(tgt);
18445039663SJohn Forte 
18545039663SJohn Forte 	PPPT_GLOBAL_UNLOCK();
18645039663SJohn Forte 
18745039663SJohn Forte 	/* Wait for delete to complete */
18845039663SJohn Forte 	mutex_enter(&tgt->target_mutex);
18945039663SJohn Forte 	while ((tgt->target_refcount > 0) ||
19045039663SJohn Forte 	    (tgt->target_state != TS_DELETING)) {
19145039663SJohn Forte 		cv_wait(&tgt->target_cv, &tgt->target_mutex);
19245039663SJohn Forte 	}
19345039663SJohn Forte 	mutex_exit(&tgt->target_mutex);
19445039663SJohn Forte 
19545039663SJohn Forte 	pppt_tgt_destroy(tgt);
19645039663SJohn Forte 	stmf_status = STMF_SUCCESS;
19745039663SJohn Forte 
19845039663SJohn Forte pppt_deregister_tgt_done:
19945039663SJohn Forte 	pppt_msg_tx_status(msg, stmf_status);
20045039663SJohn Forte 	stmf_ic_msg_free(msg);
20145039663SJohn Forte }
20245039663SJohn Forte 
20345039663SJohn Forte static void
20445039663SJohn Forte pppt_msg_session_destroy(stmf_ic_msg_t *msg)
20545039663SJohn Forte {
20645039663SJohn Forte 	stmf_ic_session_create_destroy_msg_t	*sess_destroy;
20745039663SJohn Forte 	pppt_tgt_t				*tgt;
20845039663SJohn Forte 	pppt_sess_t				*ps;
20945039663SJohn Forte 
21045039663SJohn Forte 	sess_destroy = msg->icm_msg;
21145039663SJohn Forte 
21245039663SJohn Forte 	PPPT_GLOBAL_LOCK();
21345039663SJohn Forte 
21445039663SJohn Forte 	/*
21545039663SJohn Forte 	 * Look for existing session for this ID
21645039663SJohn Forte 	 */
21745039663SJohn Forte 	ps = pppt_sess_lookup_locked(sess_destroy->icscd_session_id,
218716c1805SNattuvetty Bhavyan 	    sess_destroy->icscd_tgt_devid, sess_destroy->icscd_rport);
21945039663SJohn Forte 
22045039663SJohn Forte 	if (ps == NULL) {
22145039663SJohn Forte 		PPPT_GLOBAL_UNLOCK();
22245039663SJohn Forte 		stmf_ic_msg_free(msg);
22345039663SJohn Forte 		PPPT_INC_STAT(es_sess_destroy_no_session);
22445039663SJohn Forte 		return;
22545039663SJohn Forte 	}
22645039663SJohn Forte 
22745039663SJohn Forte 	tgt = ps->ps_target;
22845039663SJohn Forte 
22945039663SJohn Forte 	mutex_enter(&tgt->target_mutex);
23045039663SJohn Forte 	mutex_enter(&ps->ps_mutex);
23145039663SJohn Forte 
23245039663SJohn Forte 	/* Release the reference from the lookup */
23345039663SJohn Forte 	pppt_sess_rele_locked(ps);
23445039663SJohn Forte 
23545039663SJohn Forte 	/* Make sure another thread is not already closing the session */
23645039663SJohn Forte 	if (!ps->ps_closed) {
23745039663SJohn Forte 		/* Found matching open session, quiesce... */
23845039663SJohn Forte 		pppt_sess_close_locked(ps);
23945039663SJohn Forte 	}
24045039663SJohn Forte 	mutex_exit(&ps->ps_mutex);
24145039663SJohn Forte 	mutex_exit(&tgt->target_mutex);
24245039663SJohn Forte 	PPPT_GLOBAL_UNLOCK();
24345039663SJohn Forte 
24445039663SJohn Forte 	stmf_ic_msg_free(msg);
24545039663SJohn Forte }
24645039663SJohn Forte 
24745039663SJohn Forte static void
24845039663SJohn Forte pppt_msg_scsi_cmd(stmf_ic_msg_t *msg)
24945039663SJohn Forte {
25045039663SJohn Forte 	pppt_sess_t			*pppt_sess;
25145039663SJohn Forte 	pppt_buf_t			*pbuf;
25245039663SJohn Forte 	stmf_ic_scsi_cmd_msg_t		*scmd;
25345039663SJohn Forte 	pppt_task_t			*ptask;
25445039663SJohn Forte 	scsi_task_t			*task;
25545039663SJohn Forte 	pppt_status_t			pppt_status;
25645039663SJohn Forte 	stmf_local_port_t		*lport;
25745039663SJohn Forte 	stmf_scsi_session_t		*stmf_sess;
25845039663SJohn Forte 	stmf_status_t			stmf_status;
25945039663SJohn Forte 
26045039663SJohn Forte 	/*
26145039663SJohn Forte 	 * Get a task context
26245039663SJohn Forte 	 */
26345039663SJohn Forte 	ptask = pppt_task_alloc();
26445039663SJohn Forte 	if (ptask == NULL) {
26545039663SJohn Forte 		/*
26645039663SJohn Forte 		 * We must be very low on memory.  Just free the message
26745039663SJohn Forte 		 * and let the command timeout.
26845039663SJohn Forte 		 */
26945039663SJohn Forte 		stmf_ic_msg_free(msg);
27045039663SJohn Forte 		PPPT_INC_STAT(es_scmd_ptask_alloc_fail);
27145039663SJohn Forte 		return;
27245039663SJohn Forte 	}
27345039663SJohn Forte 
27445039663SJohn Forte 	scmd = msg->icm_msg;
27545039663SJohn Forte 
27645039663SJohn Forte 	/*
27745039663SJohn Forte 	 * Session are created implicitly on the first use of an
27845039663SJohn Forte 	 * IT nexus
27945039663SJohn Forte 	 */
28045039663SJohn Forte 	pppt_sess = pppt_sess_lookup_create(scmd->icsc_tgt_devid,
281716c1805SNattuvetty Bhavyan 	    scmd->icsc_ini_devid, scmd->icsc_rport,
282716c1805SNattuvetty Bhavyan 	    scmd->icsc_session_id, &stmf_status);
28345039663SJohn Forte 	if (pppt_sess == NULL) {
28445039663SJohn Forte 		pppt_task_free(ptask);
28545039663SJohn Forte 		pppt_msg_tx_status(msg, stmf_status);
28645039663SJohn Forte 		stmf_ic_msg_free(msg);
28745039663SJohn Forte 		PPPT_INC_STAT(es_scmd_sess_create_fail);
28845039663SJohn Forte 		return;
28945039663SJohn Forte 	}
29045039663SJohn Forte 
29145039663SJohn Forte 	ptask->pt_sess = pppt_sess;
29245039663SJohn Forte 	ptask->pt_task_id = scmd->icsc_task_msgid;
29345039663SJohn Forte 	stmf_sess = pppt_sess->ps_stmf_sess;
29445039663SJohn Forte 	lport = stmf_sess->ss_lport;
29545039663SJohn Forte 
29645039663SJohn Forte 	/*
29745039663SJohn Forte 	 * Add task to our internal task set.
29845039663SJohn Forte 	 */
29945039663SJohn Forte 	pppt_status = pppt_task_start(ptask);
30045039663SJohn Forte 
30145039663SJohn Forte 	if (pppt_status != 0) {
30245039663SJohn Forte 		/* Release hold from pppt_sess_lookup_create() */
30345039663SJohn Forte 		PPPT_LOG(CE_WARN, "Duplicate taskid from remote node 0x%llx",
30445039663SJohn Forte 		    (longlong_t)scmd->icsc_task_msgid);
30545039663SJohn Forte 		pppt_task_free(ptask);
30645039663SJohn Forte 		pppt_sess_rele(pppt_sess);
30745039663SJohn Forte 		pppt_msg_tx_status(msg, STMF_ALREADY);
30845039663SJohn Forte 		stmf_ic_msg_free(msg);
30945039663SJohn Forte 		PPPT_INC_STAT(es_scmd_dup_task_count);
31045039663SJohn Forte 		return;
31145039663SJohn Forte 	}
31245039663SJohn Forte 
31345039663SJohn Forte 	/*
31445039663SJohn Forte 	 * Allocate STMF task context
31545039663SJohn Forte 	 */
31645039663SJohn Forte 	ptask->pt_stmf_task = stmf_task_alloc(lport, stmf_sess,
31745039663SJohn Forte 	    scmd->icsc_task_lun_no,
31845039663SJohn Forte 	    scmd->icsc_task_cdb_length, 0);
31945039663SJohn Forte 	if (ptask->pt_stmf_task == NULL) {
320*ef3b9e2fSDan McDonald 		/* NOTE: pppt_task_done() will free ptask. */
32145039663SJohn Forte 		(void) pppt_task_done(ptask);
32245039663SJohn Forte 		pppt_sess_rele(pppt_sess);
32345039663SJohn Forte 		pppt_msg_tx_status(msg, STMF_ALLOC_FAILURE);
32445039663SJohn Forte 		stmf_ic_msg_free(msg);
32545039663SJohn Forte 		PPPT_INC_STAT(es_scmd_stask_alloc_fail);
32645039663SJohn Forte 		return;
32745039663SJohn Forte 	}
32845039663SJohn Forte 
32945039663SJohn Forte 	task = ptask->pt_stmf_task;
330*ef3b9e2fSDan McDonald 	/* task_port_private reference is a real reference. */
331*ef3b9e2fSDan McDonald 	(void) pppt_task_hold(ptask);
33245039663SJohn Forte 	task->task_port_private = ptask;
33345039663SJohn Forte 	task->task_flags = scmd->icsc_task_flags;
33445039663SJohn Forte 	task->task_additional_flags = 0;
33545039663SJohn Forte 	task->task_priority = 0;
33645039663SJohn Forte 
33745039663SJohn Forte 	/*
33845039663SJohn Forte 	 * Set task->task_mgmt_function to TM_NONE for a normal SCSI task
33945039663SJohn Forte 	 * or one of these values for a task management command:
34045039663SJohn Forte 	 *
34145039663SJohn Forte 	 * TM_ABORT_TASK ***
34245039663SJohn Forte 	 * TM_ABORT_TASK_SET
34345039663SJohn Forte 	 * TM_CLEAR_ACA
34445039663SJohn Forte 	 * TM_CLEAR_TASK_SET
34545039663SJohn Forte 	 * TM_LUN_RESET
34645039663SJohn Forte 	 * TM_TARGET_WARM_RESET
34745039663SJohn Forte 	 * TM_TARGET_COLD_RESET
34845039663SJohn Forte 	 *
34945039663SJohn Forte 	 * *** Note that STMF does not currently support TM_ABORT_TASK so
35045039663SJohn Forte 	 * port providers must implement this command on their own
35145039663SJohn Forte 	 * (e.g. lookup the desired task and call stmf_abort).
35245039663SJohn Forte 	 */
35345039663SJohn Forte 	task->task_mgmt_function = scmd->icsc_task_mgmt_function;
35445039663SJohn Forte 
35591159e90SJohn Forte 	task->task_max_nbufs = 1; /* Don't allow parallel xfers */
35645039663SJohn Forte 	task->task_cmd_seq_no = msg->icm_msgid;
35745039663SJohn Forte 	task->task_expected_xfer_length =
35845039663SJohn Forte 	    scmd->icsc_task_expected_xfer_length;
35945039663SJohn Forte 
3608f641fa7SSue Gleeson 	if (scmd->icsc_task_cdb_length) {
3618f641fa7SSue Gleeson 		bcopy(scmd->icsc_task_cdb, task->task_cdb,
3628f641fa7SSue Gleeson 		    scmd->icsc_task_cdb_length);
3638f641fa7SSue Gleeson 	}
36445039663SJohn Forte 	bcopy(scmd->icsc_lun_id, ptask->pt_lun_id, 16);
36545039663SJohn Forte 
36645039663SJohn Forte 	if (scmd->icsc_immed_data_len) {
36745039663SJohn Forte 		pbuf = ptask->pt_immed_data;
36845039663SJohn Forte 		pbuf->pbuf_immed_msg = msg;
36945039663SJohn Forte 		pbuf->pbuf_stmf_buf->db_data_size = scmd->icsc_immed_data_len;
37045039663SJohn Forte 		pbuf->pbuf_stmf_buf->db_buf_size = scmd->icsc_immed_data_len;
37145039663SJohn Forte 		pbuf->pbuf_stmf_buf->db_relative_offset = 0;
37245039663SJohn Forte 		pbuf->pbuf_stmf_buf->db_sglist[0].seg_length =
37345039663SJohn Forte 		    scmd->icsc_immed_data_len;
37445039663SJohn Forte 		pbuf->pbuf_stmf_buf->db_sglist[0].seg_addr =
37545039663SJohn Forte 		    scmd->icsc_immed_data;
37645039663SJohn Forte 
37745039663SJohn Forte 		stmf_post_task(task, pbuf->pbuf_stmf_buf);
37845039663SJohn Forte 	} else {
37945039663SJohn Forte 		stmf_post_task(task, NULL);
38045039663SJohn Forte 		stmf_ic_msg_free(msg);
38145039663SJohn Forte 	}
38245039663SJohn Forte }
38345039663SJohn Forte 
38445039663SJohn Forte static void
38545039663SJohn Forte pppt_msg_data_xfer_done(stmf_ic_msg_t *msg)
38645039663SJohn Forte {
38745039663SJohn Forte 	pppt_task_t				*pppt_task;
38845039663SJohn Forte 	stmf_ic_scsi_data_xfer_done_msg_t	*data_xfer_done;
38945039663SJohn Forte 
39045039663SJohn Forte 	data_xfer_done = msg->icm_msg;
39145039663SJohn Forte 
39245039663SJohn Forte 	/*
39345039663SJohn Forte 	 * Find task
39445039663SJohn Forte 	 */
39545039663SJohn Forte 	pppt_task = pppt_task_lookup(data_xfer_done->icsx_task_msgid);
39645039663SJohn Forte 
39745039663SJohn Forte 	/* If we found one, complete the transfer */
39845039663SJohn Forte 	if (pppt_task != NULL) {
39945039663SJohn Forte 		pppt_xfer_read_complete(pppt_task, data_xfer_done->icsx_status);
40045039663SJohn Forte 	}
40145039663SJohn Forte 
40245039663SJohn Forte 	stmf_ic_msg_free(msg);
40345039663SJohn Forte }
40445039663SJohn Forte 
40545039663SJohn Forte static void
40645039663SJohn Forte pppt_msg_handle_status(stmf_ic_msg_t *msg)
40745039663SJohn Forte {
40845039663SJohn Forte 	/* Don't care for now */
40945039663SJohn Forte 	stmf_ic_msg_free(msg);
41045039663SJohn Forte }
411